I recently completed a project that required me to write a handful of windows batch files. These files needed to be as universally compatible as possible. This unfortunately ruled out options such as cygwin, powershell, and vbscript, which would have offered me more convenience, power, and saved me significant time and headaches.
The job of the batch files was to run through a number of xml files, process them (using an external tool), and archive the results of the processing. After a few minutes researching how to write simple for loops, here is what I ended up with.
for %%X in (c:\data\*.xml) do ( c:\bin\process_data.exe %%X copy results.xml c:\results\%%X-results.xml )
After running the batch file, I was greeted with the following.
The filename, directory name, or volume label syntax is incorrect. 0 file(s) copied.
Looking more closely at what preceded the error, I noticed this
c:\tmp>c:\bin\process_data.exe c:\data\input1.xml copy results.xml c:\results\c:\data\input1-results.xml
Using copy results.xml c:\results\%%X-results.xml was resulting in the full path of the input file being appended to the destination path.
Clearly, what I was shooting for was copy results.xml c:\results\input1-results.xml as opposed to copy results.xml c:\results\c:\data\input1-results.xml. Knowing how I would handle this issue on a UNIX system, I searched in vain for command line tools that were similar to cut or awk and included with XP. After quite a bit of googling, I eventually landed on the Microsoft resource on using batch files. While the entire document contains useful information, the section that solved my issue was Using batch parameters. There are a number of parameter modifiers that “… use current drive and directory information to expand the batch parameter as a partial or complete file or directory name. ”
As it turns out the parameter modifier we want is %~n1 which “expands %1 to a file name”.
for %%X in (c:\data\*.xml) do ( c:\bin\process_data.exe %%X copy results.xml c:\results\%%~nX-results.xml )
After running the batch file, I am now seeing what I had hoped to originally.
c:\tmp>c:\bin\process_data.exe c:\data\input1.xml copy results.xml c:\results\data\input1-results.xml 1 file(s) copied.
Note: %~n1 provides just the filename, %~nx1 will provide the filename including the extension.