Windows batch file with loop through subfolders - windows

I didnt succeed writing an approriate batch file and would appreciate some help.
Let's say I have an exe in D:\Test\ called script.exe.
To execute this script.exe it requires an additional argument of a .bin files (e.g. bin01.bin, bin02.bin).
Therefore it would be like: script.exe -i bin01.bin, script.exe -i bin01
I want the script to execute with all .bin files from all subfolders
D:\Test\script.exe
D:\Test\Folder01\bin01.bin
D:\Test\Folder01\bin02.bin
D:\Test\Folder02\bin01.bin
D:\Test\Folder03\bin01.bin
anyone could help me here?
Thanks a lot in advance.

For direct execution from within a command prompt window:
for /R "D:\Test" %I in (*.bin) do #D:\Test\script.exe -i "%I"
And the same command line for usage in a batch file:
#for /R "D:\Test" %%I in (*.bin) do #D:\Test\script.exe -i "%%I"
The command FOR searches recursive in directory D:\Test and all subdirectories for files matching the wildcard pattern *.bin.
The name of each found file is assigned with full path to case-sensitive loop variable I.
FOR executes for each file the executable D:\Test\script.exe with first argument -i and second argument being the name of found file with full path enclosed in double quotes to work for any *.bin file name even those containing a space or one of these characters: &()[]{}^=;!'+,`~.
# at beginning of entire FOR command line just tells Windows command interpreter cmd.exe not to echo the command line after preprocessing before execution to console window as by default.
# at beginning of D:\Test\script.exe avoids the output of this command to console executed on each iteration of the loop.
Most often the echo of a command line before execution is turned off at beginning of the batch file with #echo off as it can be seen below.
#echo off
for /R "D:\Test" %%I in (*.bin) do D:\Test\script.exe -i "%%I"
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.
echo /?
for /?

Related

Windows Command line: how can I list all files in all folders without the location just a list of files

How can I within Windows command prompt list all files that are contained in that directory and all subdirectories but the list should only contain a list of files and not the directory location that each file is found in?
Example:
dir /d /s /b /q *.txt will get a list of all text files in all directories so I will end up with c:\example1.txt c:\folder1\example2.txt but I need only the list to show example1.txt example2.txt I hope my question is understandable. just a list of files not showing their paths?
You can try with this command in PowerShell
dir *.txt -r | % Name
From cmd you can execute like
PowerShell -Command "dir *.txt -r | % Name"
There can be used in a Windows command prompt window:
for /R %I in (*.txt) do #echo %~nxI
That results in searching recursive because of option /R in current directory and all its subdirectories for non-hidden files of which long or short 8.3 file name is matched by the wildcard pattern *.txt. Output is just the file name with extension.
Run in a command prompt window for /? to get output the help of the Windows command FOR.
There can be used in a command prompt window also:
for /F "delims=" %I in ('dir *.txt /A-D /B /S 2^>nul') do #echo %~nxI
This command line starts in background one more cmd.exe with option /c to execute the command line enclosed in ' appended as additional arguments. So there is executed in background:
C:\Windows\System32\cmd.exe /c dir *.txt /A-D /B /S 2>nul
The command DIR searches now
in current directory and all its subdirectories because of option /S
for just files because of option /A-D (all attributes except directory attribute) including also hidden files
of which long or short 8.3 name is matched by the wildcard pattern *.txt.
There is output to handle STDOUT of background command process just the list of found file names in bare format because of option /B with full path because of option /S.
It is possible that DIR does not find any file system entry matched by the criteria which results in an error message output to handle STDOUT. This error message is redirected with 2>nul to the device NUL to suppress it.
Read the Microsoft documentation about Using command redirection operators for an explanation of 2>nul. The redirection operator > must be escaped with caret character ^ on FOR command line 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.
The output list of fully qualified file names is captured by cmd.exe being opened as Windows command prompt and processed by FOR after cmd.exe started in background closed itself. So it can take some time until there is something displayed in the command prompt window depending on how much file system entries must be searched for by the command DIR of background command process.
FOR would split up by default each line into substrings using normal space and horizontal tab as string delimiters. This line splitting behavior is not wanted here and therefore the option delims= is used to define an empty list of string delimiters to turn off the line splitting. So each file name is assigned one after the other to the specified loop variable I.
The command ECHO outputs finally the file name assigned to loop variable I with just name and extension.
Run in the command prompt window also dir /? for help on this internal command of the Windows Command Processor.

Batch script to rename all files with spaces [duplicate]

This question already has answers here:
Variables are not behaving as expected
(1 answer)
Example of delayed expansion in batch file
(5 answers)
At which point does `for` or `for /R` enumerate the directory (tree)?
(1 answer)
Closed 1 year ago.
I'm trying to write a batch script that'll read all the pdf files in a folder and rename them such that there are no spaces in them. So I've typed up the below code. Although most of the parts of the code seems to work in isolation, I get an error when running the code together.
for /r %%f in (*.txt) do (
set filename=%%~nxf
set new=%filename: =%
ren "%filename%" %new%
)
The filename is detected correctly by line2. But on line3, I don't get the value I've stored in line2. Interestingly enough, if I were to run the command again in the same prompt, line3 then works (filename variable is read correctly). It must be how the for loop operates in a batch script. If I run the below code exactly 3 times in the same command prompt, the code works perfectly fine (I assume because all variables are now set correctly). Can someone please help point me in the right direction? Thanks in advance.
Note: I have a filename called "filename .txt" in the working directory, which I realise wasn't the best choice of filename. :|
(error in screenshot)
Open a command prompt, run set /? and read the output help carefully and completely from top of first to bottom of last page, especially the section about delayed expansion explained also by Variables are not behaving as expected. The Windows command processor cmd.exe processes the entire command block starting with ( and ending with matching ) before executing command FOR at all. All environment variables using %...% syntax are expanded (replaced) already during this processing phase by the appropriate variable expansion result.
So executed is the following on environment variable filename not already defined:
for /R %f in (*.txt) do (
set filename=%~nxf
set new= =
ren ""
)
That can be seen on debugging the batch file by running it from within a command prompt window instead of double clicking the batch file. This results in the following error message for each *.txt file found in current directory and all its subdirectories:
The syntax of the command is incorrect.
The syntax of the command ren is of course incorrect.
One solution is using following batch code:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
for /F "delims=" %%I in ('dir "* *.txt" /A-D /B /S 2^>nul') do (
set "FullName=%%I"
set "FileName=%%~nxI"
setlocal EnableDelayedExpansion
ren "!FullName!" "!FileName: =!"
endlocal
)
endlocal
The first two lines define completely the required execution environment for the batch file.
There is not used a for /R loop as that can cause troubles depending on file system of current drive and the file names to modify on renaming the files with file extension .txt while the FOR loop iterates of the file system entries matching the wildcard pattern.
The usage of the for /F loop results in first starting one more command process in background with %ComSpec% /c and the specified command line appended as additional arguments. So with Windows installed in C:\Windows is executed in background:
C:\Windows\System32\cmd.exe /C dir "* *.txt" /A-D /B /S 2>nul
The second command process runs DIR which
searches in current directory and all its subdirectories because of option /S
for just files because of option /A-D (attribute not directory)
of which name matches the wildcard pattern * *.txt in long or short name
and outputs the found file names in bare format because of option /B which means just the file names with full path because of option /S.
The command DIR finds also matching file names of files with hidden attribute set which are ignored by for /R. The option /A-D could be modified to /A-D-H to ignore hidden files.
The wildcard pattern contains a space character. For that reason the command DIR outputs just the full qualified file names of files which contain at least one space character in long file name. Short 8.3 file names cannot contain a space character.
The error message output by DIR if it cannot find at least one file name matching the wildcard pattern in the entire directory tree of current directory is suppressed by redirecting the error message from handle STDERR to device NUL.
Read the Microsoft documentation about Using command redirection operators for an explanation of 2>nul. The redirection operator > must be escaped with caret character ^ on FOR command line 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.
The command FOR respectively the cmd.exe instance processing the batch file captures all lines output by DIR to handle STDOUT of command process started in background. The processing of the list of full qualified file names starts when started cmd.exe closed itself after finishing execution of command DIR.
The list of file names to process is now completely in memory of the command process executing the batch file. The file renames done next by the loop cause multiply changes in file system, but that does not affect the list of file names processed by FOR as it is the case on using for /R. So there is surely no file name with a space in name skipped as the file system changes do not affect the processing of the files to rename.
FOR with option /F results by default in ignoring all empty lines. The command DIR does not output empty lines.
Next a non-empty line is split up by default into substrings using horizontal tab and normal space as string delimiters. That string splitting behavior is definitely not wanted here as the files to rename contain at least one space character. For that reason delims= is used to define an empty list of string delimiters which turns off the line splitting behavior completely.
There is by default ignored next a line of which first substring starts with default end of line character ;. But the command DIR with option /S outputs all file names with full path and it is therefore impossible that any full qualified file name starts with a semicolon. So it is not necessary to modify the default end of line character.
The full file name is assigned to loop variable I which is next assigned to the environment variable FullName. The file name with file extension without path is assigned to environment variable FileName. The environment variables are (re)defined while delayed environment variable expansion is disabled to process also file names correct containing one or more ! in name. If delayed expansion would be already enabled, each exclamation mark in file name assigned to loop variable I would be interpreted as beginning/end of a delayed expanded environment variable reference which of course is not wanted in this case.
Now delayed expansion is enabled to be able to rename the file using its full file name referenced delayed expanded and its new name without path with all spaces removed. Then the previous environment is restored which is necessary to avoid a stack overflow as there is much more done in background by setlocal EnableDelayedExpansion than toggling the state of delayed expansion and to process the next file name again in an environment with delayed expansion disabled. See this answer for details on what happens in background on each usage of the commands SETLOCAL and ENDLOCAL.
There is no guarantee that each file rename really works. The file rename fails if there is already a file or directory with new name in the directory of a file to rename. A file rename fails also if a file to rename is currently opened by an application which opened it with denying any access by another application.
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.
dir /?
echo /?
endlocal /?
for /?
ren /?
set /?
setlocal /?

Iterate folder and get filename for commandline input

I am trying to iterate files in a folder and process them with another batch file inside the do loop. It works with echo but as soon as I use the variable as input to the program, it echoes the () part and everything inside.
Here's what I'm trying to do.
#echo off
SETLOCAL ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION
for /r %%f in (/folder/*) do (
set name="%%~nf"
echo !name! <--- ok
process.bat !name! <--- echoes () and commands inside this do loop
)
ENDLOCAL
The process.bat just capitalizes the first letter of the filename and echoes it for debug or confirmation.
A batch file must be called from within a batch file using command call as otherwise Windows command processor continues processing on other batch file with never returning back to initial batch file.
See also: How to call a batch file that is one level up from the current directory?
Please read excellent answer on batch file echo on/off not working properly written by dbenham for the reason on getting suddenly the commands executed by FOR output after first execution of process.bat without using command CALL. I cannot explain better what happens in this case.
The directory separator on Windows is the backslash character \ and not the forward slash / as on Linux or Mac. Windows supports also / in file/folder paths for compatibility reasons by automatically replacing all / by \ before accessing the Windows file systems, but a good written script uses 100% correct syntax and does not depend on automatic corrections done by other programs. / is used on Windows mainly for command line switches.
The usage of / instead of \ can result in an unexpected behavior. For example run a batch file with following content:
#echo off
echo Files in directory %SystemRoot:\=/%/:
for %%I in (%SystemRoot:\=/%/*) echo %%I
echo/
pause
echo/
echo Files in directory %SystemRoot%\:
for %%I in (%SystemRoot%\*) echo %%I
echo/
pause
The first FOR using C:/Windows/* as wildcard pattern outputs the file names with just drive letter + colon + file name + file extension. The file path \Windows\ is missing in output file names. The second FOR loop using C:\Windows\* as wildcard pattern outputs the full qualified file names, i.e. drive letter + colon + file path + file name + file extension.
A file/folder path starting with \ references a directory or file relative to root directory of current DRIVE.
This is explained by the Microsoft documentation Naming Files, Paths, and Namespaces.
It looks like folder is a subdirectory in directory of the executed batch file. In this case / or \ at beginning of folder path is definitely not correct. The backslash at beginning can be omitted or .\ is used to reference the directory folder in current directory on execution of the batch file. But the current directory on batch file execution can be also different to directory containing the executed batch file, for example on running the batch file as administrator, or on running the batch file as scheduled task, or on running the batch file from a network resource accessed using a UNC path. For that reason it is advisable to reference explicitly subdirectory folder in directory of the batch file.
Delayed environment variable expansion is not needed as long as the file name assigned currently to the loop variable does not need to be modified other than the modifiers of for support it. A command line like set name="%%~nf" does not work correct with enabled delayed expansion and file name contains one or more ! because of cmd.exe interprets the exclamation mark(s) in file name as beginning/end of a delayed expanded environment variable reference.
See also: How does the Windows Command Interpreter (CMD.EXE) parse scripts?
It looks like a recursive search for non-hidden files is not really needed as otherwise passing just file name without path and file extension would be not enough to get the right file processed by other batch file process.bat.
So the entire task can be done most likely also with:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
for %%I in ("%~dp0folder\*") do call "%~dp0process.bat" "%%~nI"
endlocal
But if the other batch file process.bat expects that the passed file name without file extension and path is in current directory on execution of process.bat, it is necessary to make the subdirectory folder in directory of this batch file first the current directory.
#echo off
setlocal EnableExtensions DisableDelayedExpansion
pushd "%~dp0folder"
for %%I in (*) do call "%~dp0process.bat" "%%~nI"
popd
endlocal
Note: The batch file folder path referenced with %~dp0 always ends with a backslash. Therefore no additional backslash should be used on concatenating this path string with a file/folder name to avoid having finally on execution of the batch file \\ in full qualified file/folder name, although Windows kernel corrects such paths also automatically by removing second backslash in this case.
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 /?
echo /?
endlocal /?
popd /?
pushd /?
set /?
setlocal /?

Command prompt: loop and run command on all files

I am new to using command prompt. I have a large amount of zip files I need to run a program on.
Running the program on one of the files in the command prompt looks like this:
Tabulate.exe -i S:\Packages\ZipFolderName_1.zip -o S:\Output\ZipFolderName_1
which spits out a csv.
I have found these posts helpful, but cannot seem to implement for my situation:
Iterate all files in a directory using a 'for' loop
Loop on files and run command
Read entire for /? output, pay your attention to ~ modifiers. In the following cmd compound command is used ECHO to merely show Tabulate.exe lines to be executed:
for %I in ("S:\Packages\*.zip") do #ECHO Tabulate.exe -i %~fI -o S:\Output\%~nI
To use the FOR command in a batch program, specify %%variable
instead of %variable. Variable names are case sensitive, so %i is
different from %I.
#ECHO OFF
SETLOCAL EnableExtensions
for %%I in ("S:\Packages\*.zip") do (
rem explaining comments:
rem %~fI expands %I to a fully qualified path name
rem %~nI expands %I to a file name only ↓↓↓↓
ECHO Tabulate.exe -i %%~fI -o S:\Output\%%~nI
rem ↑↑↑↑ remove `ECHO` no sooner than debugged
)

Command line: how to use the content of a text file as an input argument to a program in windows?

In one directory I have two files:
'program.exe' and 'content.in'
How do I start 'program.exe' with the content of 'content.in' as an argument from the command-line in windows ?
Thanks.
You can also accomplish this by putting the contents of the file into a variable, borrowing the second half of this answer.
set /p VV=<content.in
program.exe %VV%
If 'program.exe' accepts input from standard in you would
program.exe < content.in
If it doesn't then you are dependent on the program processing files through command arguments, potentially like
program.exe content.in
or
program.exe -i content.in
You probably want
for /F "tokens=*" %i in ('content.in') do program.exe %i
(In a batch file, replace %i with %%i.)
Note that if content.in contains more than one line of text, program.exe will be run multiple times, once for each line.

Resources