How to use subfolders with the FOR command? - file

I'm trying to use the FOR /f command to calculate the filesize of multiple files with the same extension. I have this so far:
FOR /F "usebackq" %%A IN ('C:\Users\%username%\*.bat') DO set size=%%~zA
If I have 3 batch files under the desktop, and 2 under my documents, I want the batch file to get the size of each and display all 5 together. I have the command working perfectly if I use just a single directory with batch files, but all I need is for it to include subdirectories. The current line I have above displays ECHO is off because there are NO batch files under the path C:\Users\%username%. I have batch files on my desktop, and I need it to include it since it's a subdirectory. How can I get this command to include subdirectories?

FOR /R
Loop through files (Recurse subfolders)
Syntax
FOR /R [[drive:]path] %%parameter IN (set) DO command
Key
drive:path : The folder tree where the files are located.
set : A set of one or more files. Wildcards must be used.
If (set) is a period character (.) then FOR will
loop through every folder.
command : The command(s) to carry out, including any
command-line parameters.
%%parameter : A replaceable parameter:
in a batch file use %%G (on the command line %G)
This command walks down the folder tree starting at [drive:]path, and executes the DO statement against each matching file.
If the [drive:]path are not specified they will default to the current drive:path.
Unlike some other variants of the FOR command you must include a wildcard (either * or ?) in the 'set' to get consistent results returned. In many cases you can work around this by adding a single character wildcard e.g. if you are looping through multiple folders to find the exact filename myfile.txt you could instead specify myfile.t?t
http://ss64.com/nt/for_r.html

dir is far easier.
dir "%userprofile%\*.bat" /a /s
or just the sizes
dir "%userprofile%\*.bat" /a /s|findstr /c:"File(s)"

Related

Need a Batch File to Create and Name m3us in Subdirectories

I have a main directory with hundreds of subdirectories, each containing one or more .cue files.
Main Directory
|
+---Subdirectory1
| .cue1
| .cue2
|
+---Subdirectory2
| .cue1
|
+---etc.
I need a batch file which I can run in Main Directory, and will create a .m3u file in each subdirectory. The .m3u file should be named matching its parent directory name, with content listing each .cue file it shares that parent with, but as a relative path.
I found this script online:
rem Execute it in the directory which includes music files
rem It requires one argument which will become created m3u playlist file's name
for %%i in (*.mp3,*.mp4,*.m4a,*.wma,*.wav) do echo %cd%\%%i >> %1.m3u
I know enough to modify (*.mp3,*.mp4,*.m4a,*.wma,*.wav) to (*.cue) and it works if I put it into a subdirectory, but the .m3u it produces is nameless, and the paths inside it are absolute. (I can actually work with the absolute paths to the .cue files if making them relative is impossible, but it would take a long time to run this in every directory and rename the m3us as I went.)
Any help would be appreciated.
This task can be done on NTFS drives returning a list of file names sorted by name with:
#echo off
for /R "%~dp0" %%I in (*.cue) do for %%J in ("%%~dpI.") do echo %%~nxI>>"%%~dpI%%~nxJ.m3u"
The following batch code is better for FAT16, FAT32 and exFAT drives to get the *.cue file names written ordered by name into the *.m3u files.
#echo off
for /F "eol=| delims=" %%I in ('dir "%~dp0*.cue" /A-D-H /B /ON /S 2^>nul') do for %%J in ("%%~dpI.") do echo %%~nxI>>"%%~dpI%%~nxJ.m3u"
The batch file should be stored in Main Directory. Otherwise %~dp0 referencing the drive and path of the batch file ending always with \ must be replaced by full path of Main Directory ending also with a backslash.
The outer FOR processes all non-hidden full qualified *.cue file names (drive + path + name + extension) found recursively in the specified directory and all its subdirectories. The inner FOR runs always just once for every file name to get from full qualified file path of current file the name of the directory containing this file to name the *.m3u file like the directory.
For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.
call /? ... explains %~dp0 - drive and path of argument 0 which is the full qualified path of the batch file.
dir /?
echo /?
for /?
Read the Microsoft article about Using command redirection operators for an explanation of >> and 2>nul. The redirection operator > must be escaped with caret character ^ on FOR command line running DIR to be interpreted as literal character when Windows command interpreter processes this command line before executing command FOR which executes the embedded dir command line with using a separate command process started in background with %ComSpec% /c and the command line within ' appended as additional arguments.

how to move newest file in directory and then process the rest of the script

so i'm trying to take one file at a time out of a directory that contains 2000 files and going up and move it to a different directory to be worked on by the rest of my script. the script is below. Right now i know the gswin64 line works when it is alone and i specify it a filename but not i'm sure with the variable yet. But when i run this it will copy all the files in directory input to directory working before it runs the rest of the script. How do i make it do one at a time then process the script before copying the rest of the files?
for /F "delims=" %%I in ('dir "H:\documents\gs\input\*.*" /A-d /B /O:-D') do (move "H:\documents\gs\input\%%I" "H:\documents\gs\working"&goto filemoved)
:filemoved
Your original code would attempt to execute move "H:\documents\gs\input\*.*" "H:\documents\gs\working" which is why all of th files were moved. What you need to do is execute a directory list command with the switch parameters and supply that to the for /f. This form of dir will show names only. so you need to include the source directory name in the move command. You would also need to have the "delims=" option to ensure that filenames containing separators are processed correctly, and the /a-d directory switch to ensure that directory names are not included. Since you are sorting in reverse-date order, the newest file will be selected first. After the first file is moved, you need to abort the for loop otherwise it will continue processing the entire list, transferring every file. The easy way here is to simply goto a label on the next line.
You've also used a *.* filemask, which will process all files, regardless of extension. Since you appear to want to process only .pdf files, you should probably change that filemask to suit.
for /F "delims=" %%x in ('dir H:\documents\gs\working\*.pdf /b') do set "FileName=%%x"
Again, you need to execute a dir command if you are using a for /f. There's no apparent reason why you wouldn't use the far simpler
for %%x in (H:\documents\gs\working\*.pdf) do set "FileName=%%x"
In either case, you probably want only the name part of the file, so FileName should be set to %%~nx, not %%x.
"C:\program files\gs\gs9.20\bin\gswin64" -o H:\documents\gs\output\"%FileName%" -sDevice=pdfwrite -dFitPage -dFIXEDMEDIA H:\documents\gs\working\"%FileName%"
Unbalanced quotes - the full pathname to the executable needs to be quoted since it contains a separator. Stray spaces after \ will probably need to be removed.
It would be better imho to quote the entire filename, including drive and path rather than filename only.
del /q H:\documents\gs\working\*.*
rm is not a batch command. Note that this command will delete ALL files in H:\documents\gs\working - not just the .pdf files that you appear to be processing.
goto start
The space is required. gotostart is not an inbuilt command.

I wish to delete a line in a file containing a particular word. (*KEYWORD)

I wish to delete a line contaning a specific word (in my case it is [*KEYWORD]). Those files are having an extension '.blk'. These files are located in different subfolders in the same folder. I have written this followng code.
#setlocal enabledelayedexpansion
#echo off
dir "C:\Users\XFIWSM\Desktop\batch_files\T30\*.blk /s/b > dirlist.txt
for /F %%i in (dirlist.txt) do (
type %%i
findstr /v "KEYWORD"
> %%i.blk
)
pause
As per ansswer provided by Mr. Ken, i have tried with above code. But, nothing seems to work. i have created an empty file named dirlist.txt . But this file is also not being written with path of *.blk files. Also i wish to save the .blk file with same name at the same location. Therefore, i am trying to use > %%i.blk ... Can anyone please help me, where am i going wrong ?
You can't use type on files that aren't in the specified directory the way you are (your files are in subfolders of the specified directory, not in the directory itself).
My suggestion would be to use a dir command, with the appropriate switches to search subdirectories (/s) and to produce a bare listing (without sizes, dates, and folder/volume names) (/b), and redirect that to a text file. You can then use a for /f loop to read each line in that directory listing and process it further.
#setlocal enabledelayedexpansion
#echo off
dir "D:\Master\SPRINGBACK\DPK\T08\*.blk /s/b > dirlist.txt
for /F %%i in (dirlist.txt) do (
:: Process each file here
)
For information about removing a specific line of text from a file, you can see How to remove lines (or text in given lines) from file in batch?
if you have a machine with grep, (checkout unxutils on sourceforge if using windows), you could use this commmand:
grep "KEYWORD" -v *.blk > filewithlineremoved.blk

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?

Bat file find folder of 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
)

Resources