Bat file find folder of file - batch-file

So my many attempts to search for a solution have resulted in a million ways to find the folder of the bat file being executed, however what I am looking to do is find the folder for the filename being passed to the bat file.
Example:
C:\Temp\runthis.bat "C:\Blah\Ah Argh\rage.txt"
I want to get a string within that bat file that is simply "C:\Blah\Ah Argh\", alternatively I would also be able to work with getting a string of "rage.txt"
Editing to explain why: Looking to check for the filename within another txt file which is the directory listing of a ftp server to verify that a file successfully uploaded to it. Then if successful I need to move the file to a subfolder of the original folder \uploaded\ but we have many of these folders setup so I can't hard code it.
Thanks

#echo off
The file path is %~dp1
The file name is %~nx1
The parameter modifiers are the same as for FOR variables.
Type 'HELP CALL' from a command prompt for a full list of parameter modifiers.

#echo off
if %1X==X echo Syntax: %0 "path"
rem The for loop doesn't actually loop. You can split strings with it, but in
rem this case we don't. So there is only one iteration in which %%X will
rem contain the full path.
rem Pass it %1, which is the first parameter. Note the quotes, which are
rem required if you don't add quotes around the parameter and optional (but
rem still valid) when you do.
for /F "delims=|" %%X in ("%1") do (
rem FOR LOOP variables can be used with certain modifiers, preceeded by a
rem tilde. In this case I'm using d and p, which stand for drive and path,
rem effectively trimming the file name from the path.
echo %%~dpX
rem The ~n modifier selects the file name only. ~x is for extension
echo %%~nxX
)

Related

CMD IF statement with IMAGE Dimmensions

So I need CMD if statement script to move files to certain folders depending on image name. In other words, script needs to check image file name: 123456_large.jpg and move it to folder LARGE. But once file is moved to this folder it needs to be renamed to: 123456.jpg instead of 123456_large.jpg...
So if statement finds *_LARGE.jpg, move to LARGE folder and rename filename to delete _LARGE.
Anyone any ideas?
Assuming all the files are in one common folder and the large directory also exists in that common folder you could use this.
#echo off
FOR /F "tokens=1* delims=_" %%G IN ('dir /a-d /b *.jpg') DO (
IF /I "%%~nH"=="large" move "%%~G_%%~H" "large\%%~G%%~xH"
)
So essentially what this code does:
Gets a listing of all jpg files in the current folder the batch file is in.
Splits the file name at the first underscore and assigns the first part of the file name to the variable %%G and the rest of the file name to %%H.
Using the FOR variable modifiers, it then checks if the second part of the filename without the extension is equal to large. If it is, it then moves the file and renames it at the same time, again using the FOR variable modifiers.
If you want to read about the FOR modifiers open up a cmd prompt and type: FOR /?
It is the very last section of the help file.
This worked absolutely perfect! Now a few improvements... Is there a way to do the same thing a previous script, but if file is named: 123456_ALT1_large.jpg (or ALT2, ALT3, ALT4)?

How to do MSBuild's GetDirectoryNameOfFileAbove in a batch file?

In MSBuild, there's the GetDirectoryNameOfFileAbove function that finds the first ancestor directory that includes certain file.
For those not familiar with that MSBuild function, here's an example.
I have a file:
c:\projects\root.txt
I want to be able to run a script such as:
c:\projects\everything\foo\bar\myscript.cmd
And would like to find c:\projects\, since it's the closest ancestor to c:\projects\everything\foo\bar\ that has that file in it. The script should also be able to detect when the files is not present in any of the ancestors and just get an empty string.
How do I achieve the same in a (Windows) batch script?
#echo off
setlocal EnableDelayedExpansion
set "theFile=%~1"
rem Get the path of this Batch file, i.e. "c:\projects\everything\foo\bar\"
set "myPath=%~DP0"
rem Process it as a series of ancestor directories
rem i.e. "c:\" "c:\projects\" "c:\projects\everything\" etc...
rem and search the file in each ancestor, taking as result the last one
set "result="
set "thisParent="
set "myPath=%myPath:~0,-1%"
for %%a in ("%myPath:\=" "%") do (
set "thisParent=!thisParent!%%~a\"
if exist "!thisParent!%theFile%" set "result=!thisParent!"
)
if defined result (
echo %result%
) else (
echo There is not such file in my ancestors
)
Put the name of the file as parameter of this Batch file. For example, if you name this file GetDirectoryNameOfFileAbove.bat, you may use it this way:
GetDirectoryNameOfFileAbove root.txt
I can name that tune in 2 (long lines). The code is short. The explanation is long.
#rem will search up to 8 levels up from here
#Set Ancestry=.;..;..\..;..\..\..;..\..\..\..;..\..\..\..\..;..\..\..\..\..\..;..\..\..\..\..\..\..;..\..\..\..\..\..\..;..\..\..\..\..\..\..\..;..\..\..\..\..\..\..\..\..;
#REM %~dp$Ancestry:1 -- search paths in Ancestry for arg 1
#REM finds files of any type, not just exe
#REM LocalTop is either the folder where arg 1 (%1) was found or empty
#Set LocalTop=%~dp$Ancestry:1
How it works:
Ancestry is a series of places to look: . then .., then .... and so on. I stopped at 8 levels. Add more, although I have never needed more levels.
The next line uses the magic of cmd. Note this only syntax works for %0..%9 or in a for statement with the for variable.
From FOR /?:
%~$PATH:I - searches the directories listed in the PATH
environment variable and expands %I to the
fully qualified name of the first one found
If the environment variable name is not
defined or the file is not found by the
search, then this modifier expands to the
empty string
What was not obvious to me, is that it is not limited to the environment variable 'PATH'. You may supply any variable, which is what Ancestry is above.

Use Dos commands to copy file and preserve date in file name

I'm having trouble trying to copy and rename a file using only dos commands. I have a file of the format myfile20130218 and want to copy and rename it to some_other_file_20130218.
I know I can use copy source dest but I'm having trouble with how to isolate the date and preserve it. I cannot guarantee that he date will be today's date so that is ruled out, the source file will always be the same name.
I can run either a series of commands or a batch script, but thing that that I am currently having trouble with, is after I find a match that I need to copy, using myfile????????, how can I now get those file names to pull the dates off them?
EDIT: for clarification I will be looking at files in a known directory, as above, I will know the format of the file name, and will only be checking a specific directory for it. The process that checks the directory is a ConnectDirect file watcher, so when a file is found matching myfile20130218 I can fire off some commands, but don't know how to check the directory and get the name of the file present.
Something like this should work:
%oldname:~-8% extracts the last 8 characters from %oldname% which are then appended to the new filename.
Update: If you can identify the file with an external program and then call the batch script with the file name
copyfile.cmd C:\path\to\myfile20130218
you could do something like this:
set oldname=%~nx1
set newname=%~dp1some_other_file_%oldname:~-8%
copy "%~f1" "%newname%"
Update 2: If you know folder and the format you could call the script with the folder
copyfile.cmd C:\folder
and do something like this:
#echo off
setlocal EnableDelayedExpansion
for /f %%f in (
'dir /b "%~f1" ^| findstr /r "myfile[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]$"'
) do (
set oldname=%~f1\%%f
set newname=%~f1\my_other_name_!oldname:~-8!
copy "!oldname!" "!newname!"
)
endlocal
Edit: Script breakdown.
setlocal EnableDelayedExpansion enables variable expansion inside loops and conditionals.
for /f %%f in ('...') executes the command between the single quotes and then loops over the output of that command.
dir /b "%~f1" lists the content of the given directory (%~f1 expands to the full path of the first argument passed to the script) in simple mode (no header, no summary).
findstr /r "myfile[0-9]...[0-9]$" filters the input for strings that end with the substring "myfile" followed by 8 digits. The circumflex before the pipe (^|) escapes the pipe, because otherwise it would take precedence over the for command, which would effectively split the for command in half, resulting in an invalid command-line.
set oldname=%~f1\%%f assign the full path to a matching file to the variable oldname.
set newname=%~f1\my_other_name_!oldname:~-8! assign the full path to the new filename ("my_other_name_" followed by the trailing 8 digits from oldname) to the variable newname.
copy "!oldname!" "!newname!" I don't need to explain this, do I?

Change file extensions and name at once using batch file

I have a directory full of files output from some software as below:
Pending.001
Pending.002
Pending.003
etc.
I would like to use a .bat to rename them as below:
Pending001.csv
Pending002.csv
Pending003.csv
etc.
Any suggestions?
You could rename your files in a loop, using the modifiers ~n and ~x on the loop variable to extract, respectively, the name and the extension of each file to concatenate them in the new name. As the extension would be extracted together with the leading ., you would also need a variable to temporarily store the extension before removing the ..
Here's an example of how the above could be implemented:
#ECHO OFF
FOR %%I IN (Pending.*) DO (
SET "ext=%%~xI"
SETLOCAL EnableDelayedExpansion
RENAME "%%I" "%%~nI!ext:~1!.csv"
ENDLOCAL
)
The delayed expansion is enabled because it is needed for the evaluation of ext. "Normal" expansion, which uses %, wouldn't work here because that way the variable would be expanded just once before the loop started, when the variable was still empty. In contrast, with the delayed expansion, the variable will be expanded every time the particular command containing it is executed, i.e. on every iteration of the loop too.
The above batch file would process files in the current directory, i.e. you would first need to change to the directory where the files need to be processed, then call the batch. Or, if you would be doing that in e.g. Windows Explorer, you would likely need to copy that batch to the directory with the files to process and call it from there.
Alternatively, though, you might want to call it with a parameter specifying the directory to process. To use the parameter, change the script like this:
#ECHO OFF
FOR %%I IN ("%~1\Pending.*") DO (
SET "ext=%%~xI"
SETLOCAL EnableDelayedExpansion
RENAME "%%I" "%%~nI!ext:~1!.csv"
ENDLOCAL
)
Of course, you could also just specify a fixed path to the files if they are always in the same directory:
#ECHO OFF
FOR %%I IN ("D:\path\to\files\Pending.*") DO (
SET "ext=%%~xI"
SETLOCAL EnableDelayedExpansion
RENAME "%%I" "%%~nI!ext:~1!.csv"
ENDLOCAL
)
That way you would be able to call the batch from wherever you stored it.
Why don't you refer to these posts:
How can I mass rename files from the command line or using a 3rd party tool?
Bulk Rename Command
Bulk Rename Utility
Using batch files

A batch to rename

I would like to rename a file as its parent folder example:
D:\Books\PDF\medical\001\99.jpg
D:\Books\PDF\medical\002\gg.jpg
to be:
D:\Books\PDF\medical\001\001.jpg
D:\Books\PDF\medical\002\002.jpg
I know this question asked before but I could not understand it.
also if it is possible I would like to put it in D:\Books\PDF\medical\
How to do it:
This is pretty easy:
1) Create a new text file named "myrename.bat" in "D:\Books\PDF\medical\".
2) Paste the following into it:
#echo off
pushd %~p1
for %%d in ("%CD%") do set "parentdir=%%~nd"
popd
move /Y %1 D:\Books\PDF\medical\"%parentdir%%~x1" > nul
3) From "D:\Books\PDF\medical\", run the batch file with its first argument being the name
of the file to be renamed. For instance, here's what you would do for the file "gg.jpg" in your example:
myrename 002\gg.jpg
This will rename the file "99.jpg" to "002.jpg" and move it to "D:\Books\PDF\medical\".
How it works
In batch, %~p1 returns the relative path of the first argument, i.e. it strips the folder. For instance, if you run myrename Bla\002\gg.jpg, %~p1 would be Bla\002. pushd then steps into this directory.
The for loop is supposed to extract the last folder from the current path, given by %CD%, and the value of %CD% is assigned to %%d. The expression %~nd is used to discard everything but the name of the last folder, the obtained result being stored in the variable parentdir. popd then returns to the original directory.
The move command both renames the file and moves it. The new filename is the value of parentdir and the extension %~x1, which is the extension of the original input file.
Hope this helps.

Resources