Batch file to create files using a file containing file names
February 28, 2011 3:38 PM Subscribe
Windows batch file help: I have a file containing a list of files, I want to generate a new file for each of the files in the list.
I have filenames.txt, which contains a list of file names with no extension, i.e.:
I need a batch file that will create a .abc file for each of these files and contains data that also includes the file name:
I found something close on a forum and modified it to:
There are about 85 lines I want to output to each of the 275 files I'm creating. The problem I'm running into is when I have more than five or so ECHOs I get the error, "The process cannot access the file because it is being used by another process" when running the batch file.
What am I doing wrong? Also, I do have Python installed on my PC, if this is best handled in that environment (even though I know almost nothing about Python). Thanks!
I have filenames.txt, which contains a list of file names with no extension, i.e.:
file1
file2
file3
I need a batch file that will create a .abc file for each of these files and contains data that also includes the file name:
[Setting1]
Value1=2.0
[Setting2]
SrcFile=C:\some files\file1.xyz
HostName=MyHost
[Setting3]
...
I found something close on a forum and modified it to:
@echo off
del C:\some files\*.abc
for /f "tokens=* delims=" %%a in (filenames.txt) do (
echo [Setting1] >>.\%%a.abc
echo Value1=2.0 >>.\%%a.abc
echo [Setting2] >>.\%%a.abc
echo SrctFile=C:\some files\file1.xyz >>.\%%a.abc
echo HostName=MyHost >>.\%%a.abc
echo [Setting3] >>.\%%a.abc
...
)
There are about 85 lines I want to output to each of the 275 files I'm creating. The problem I'm running into is when I have more than five or so ECHOs I get the error, "The process cannot access the file because it is being used by another process" when running the batch file.
What am I doing wrong? Also, I do have Python installed on my PC, if this is best handled in that environment (even though I know almost nothing about Python). Thanks!
Best answer: er, you probably want
posted by and for no one at 4:02 PM on February 28, 2011
open(name+extension, "w")instead of
open(name+extension, "wb")
posted by and for no one at 4:02 PM on February 28, 2011
Response by poster: Thank you, and for no one, that did the trick!
Man, I really gotta learn Python.
posted by DakotaPaul at 4:08 PM on February 28, 2011
Man, I really gotta learn Python.
posted by DakotaPaul at 4:08 PM on February 28, 2011
I can't recommend Python enough. Good luck.
posted by and for no one at 4:15 PM on February 28, 2011
posted by and for no one at 4:15 PM on February 28, 2011
Best answer: It's actually quite doable - concise even - in cmd script. This works:
Redirecting the del command's output to nul suppresses complaints if there are no files to delete.
There's no need for "tokens=*" in the for /f args, because with "delims=" there can be only one token anyway.
Using %%~f instead of %%f strips any surrounding double-quotes that may occur in the expansion of %%f. Not strictly necessary in this application, but generally good practice.
Using a single write redirection to cover the entire group of echo statements instead of individual append redirections on each echo is clearer and less error-prone.
Using echo. means you'll have no trouble if you need to echo a blank line.
Any time you need a ) in your output files, you'll need to write that as ^) inside the appropriate echo statement; without that, the ) will be taken as terminating the statement group controlled by the for command.
posted by flabdablet at 5:10 PM on February 28, 2011
set dir=C:\Some files set ext=abc del /f /q "%dir%\*.%ext%" >nul for /f "delims=" %%f in (filenames.txt) do >"%dir%\%%~f.%ext%" ( echo.[Setting1] echo.Value1=2.0 echo.[Setting2] echo.SrcFile=%dir%\%%~f.%ext% echo.HostName=MyHost echo.[Setting3] echo.... )Subtleties:
Redirecting the del command's output to nul suppresses complaints if there are no files to delete.
There's no need for "tokens=*" in the for /f args, because with "delims=" there can be only one token anyway.
Using %%~f instead of %%f strips any surrounding double-quotes that may occur in the expansion of %%f. Not strictly necessary in this application, but generally good practice.
Using a single write redirection to cover the entire group of echo statements instead of individual append redirections on each echo is clearer and less error-prone.
Using echo. means you'll have no trouble if you need to echo a blank line.
Any time you need a ) in your output files, you'll need to write that as ^) inside the appropriate echo statement; without that, the ) will be taken as terminating the statement group controlled by the for command.
posted by flabdablet at 5:10 PM on February 28, 2011
Response by poster: Thanks for the cmd script knowledge, flabdablet! My next problem is making multiple copies of the same files, i.e:
Which contain the data:
All of which is still only based on the original filenames.txt.
posted by DakotaPaul at 9:44 PM on February 28, 2011
file1(part01).abc
file1(part02).abc
file1(part03).abc
file2(part01).abc
file2(part02).abc
file2(part03).abc
file3(part01).abc
file3(part02).abc
file3(part03).abc
...
Which contain the data:
Setting1]
Value1=2.0
[Setting2]
SrcFile=C:\some files\file1(part01).xyz
HostName=MyHost
[Setting3]
...
Setting1]
Value1=2.0
[Setting2]
SrcFile=C:\some files\file1(part02).xyz
HostName=MyHost
[Setting3]
...
All of which is still only based on the original filenames.txt.
posted by DakotaPaul at 9:44 PM on February 28, 2011
This works:
Also, horrible kludges are going to be necessary if you need %%n greater than 9, because cmd's string handling is abysmally clumsy. It can still be made to work, but don't try doing so without a safety net. And a vomit bucket.
posted by flabdablet at 11:45 PM on February 28, 2011
set dir=C:\Some files set ext=abc del /f /q "%dir%\*.%ext%" >nul for /f "delims=" %%f in (filenames.txt) do ( for /l %%n in (1,1,3) do >"%dir%\%%~f(part0%%n).%ext%" ( echo.[Setting1] echo.Value1=2.0 echo.[Setting2] echo.SrcFile=%dir%\%%~f(part0%%n^).%ext% echo.HostName=MyHost echo.[Setting3] echo.... ) )Extra-subtle subtlety: even though the redirection >"%dir%\%%~f(part0%%n).%ext%" is contained within the parentheses associated with the outer for loop, there is no ^ required before its embedded ). This may be because of the double-quotes, or because redirections are processed before anything else; not sure.
Also, horrible kludges are going to be necessary if you need %%n greater than 9, because cmd's string handling is abysmally clumsy. It can still be made to work, but don't try doing so without a safety net. And a vomit bucket.
posted by flabdablet at 11:45 PM on February 28, 2011
Here's an example that generates names with (part00) through (part15) embedded in them:
The other necessary piece of nasty here is the use of setlocal enabledelayedexpansion to make the !variable! construct available. This works just like %variable% except that it happens just before command invocation instead of early in the parsing process. Using %num% and %name% instead of !num! and !name! would result in their values being expanded during the parsing of the outer for loop, which would make the set num and set name commands inside the inner loop useless.
You can see the difference if you run this thing with echo left on: where %dir% and %ext% appear in the script you'll see their expanded values echoed to the cmd window every time, while !num! and !name! echo as themselves even though their expanded values do get used to build the output filenames and content.
Doing this in Python would probably involve fewer test iterations and rather less swearing and nausea. I think it's only an unwillingness to admit defeat that keeps me writing things with cmd.
posted by flabdablet at 12:51 AM on March 1, 2011
setlocal enabledelayedexpansion set dir=%temp%\Some files set ext=abc del /f /q "%dir%\*.%ext%" >nul for /f "delims=" %%f in (filenames.txt) do ( for /l %%n in (100,1,115) do ( set num=%%n set name=%dir%\%%~f(part!num:~1!^).%ext% >"!name!" ( echo.[Setting1] echo.Value1=2.0 echo.[Setting2] echo.SrcFile=!name! echo.HostName=MyHost echo.[Setting3] echo.... ) ) )The key thing here is that the inner loop runs not from 0 to 15 but from 100 to 115. That means that set num=%%n will always make num a three-digit string; the construct !num:~1! then drops the first character, resulting in the desired two-digit string between 00 and 15.
The other necessary piece of nasty here is the use of setlocal enabledelayedexpansion to make the !variable! construct available. This works just like %variable% except that it happens just before command invocation instead of early in the parsing process. Using %num% and %name% instead of !num! and !name! would result in their values being expanded during the parsing of the outer for loop, which would make the set num and set name commands inside the inner loop useless.
You can see the difference if you run this thing with echo left on: where %dir% and %ext% appear in the script you'll see their expanded values echoed to the cmd window every time, while !num! and !name! echo as themselves even though their expanded values do get used to build the output filenames and content.
Doing this in Python would probably involve fewer test iterations and rather less swearing and nausea. I think it's only an unwillingness to admit defeat that keeps me writing things with cmd.
posted by flabdablet at 12:51 AM on March 1, 2011
By the way, it is the double-quotes that make ^) unnecessary inside the previous version's redirection.
posted by flabdablet at 12:54 AM on March 1, 2011
posted by flabdablet at 12:54 AM on March 1, 2011
And now I see I've missed the fact that you wanted .abc extensions on the generated files but .xyz extensions on the SrcFile= lines inside them. So just get rid of my %ext% variable and do it like this:
posted by flabdablet at 1:05 AM on March 1, 2011
setlocal enabledelayedexpansion set dir=C:\Some files del /f /q "%dir%\*.abc" >nul for /f "delims=" %%f in (filenames.txt) do ( for /l %%n in (100,1,115) do ( set num=%%n set name=%dir%\%%~f(part!num:~1!^) >"!name!.abc" ( echo.[Setting1] echo.Value1=2.0 echo.[Setting2] echo.SrcFile=!name!.xyz echo.HostName=MyHost echo.[Setting3] echo.... ) ) )Also, because all the file content gets generated using a write-redirect rather than an append-redirect, you might not actually need the del command.
posted by flabdablet at 1:05 AM on March 1, 2011
This thread is closed to new comments.
MeFi likes to mangle Python source, but here goes:
posted by and for no one at 3:56 PM on February 28, 2011