Batch processing files in Windows

Most convenient way to mass-process files in Windows is to use FOR loop.

Windows inherited batch scripting from MS-DOS, old operating system, with all its inconsistencies and peculiar syntax. To use a FOR loop in Windows add below code to your .BAT file:

SETLOCAL EnableDelayedExpansion

FOR %%G IN (input\*.png) DO (
...do stuff
)

explanation

  1. %G is name of a variable that stores name of the file from input folder. *.png that follows filters out everything but PNGs.
  2. SETLOCAL EnableDelayedExpansion is required for Windows to properly expand values in the loop. If we do not declare this option, %%G will be set to name of file that was found first. More on this peculiar mechanism can be found here: https://ss64.com/nt/delayedexpansion.html. A notable quote:

The SET command was first introduced with MS-DOS 2.0 in March 1983, at that time memory and CPU were very limited and the expansion of variables once per line was enough. Delayed Expansion was introduced some 16 years later in 1999 by which time millions of batch files had been written using the earlier syntax. Retaining immediate expansion as the default preserved backwards compatibility with existing batch file.

example

Script below adds black 4 pixel border to all PNG images from input directory. Results are saved to output folder, changing file name from filename.png to filename-border.png.

SETLOCAL EnableDelayedExpansion

FOR %%G IN (input\*.png) DO (
        magick ^"%%G^" -bordercolor #000000 -border 4 ^"output\%%~nG-border.png^" 
)

explanation

  1. things may go wrong if you don't proof your script against whitespaces in the filenames. To prevent script go amiss, put quotes around filenames. In batch scripting quotes need to be escaped. Contrary to POSIX \ in Windows you escape a character with a preceding ^. In other words ^"%%G^" puts quotes around filename stored in variable %G.
  2. %%~nG is Windows idiom that expands to name of currently processed file. %%~xG expands to file extension so we could write %%~nxG if we wanted to preserve same filename and extension. But in our case, as we add -border suffix, it made more sense to get just the filename. More on this variable expanding can be read here: http://www.embeddedframeworks.com/cmds/nt/syntax-args.html