| Processing a List of Text from a File |
One of the more frequently asked questions on the net concerns the processing of a list of text, such as a directory listing, in a batch procedure. Windows NT users have a real advantage in the much expanded FOR command. They need only to add the /F switch to the line to make it process text contained in a file named in the (Set) part of the command (NT users: Type FOR /? at a command prompt for more info).For those of us using DOS/Win 3.1x/Win 9x, the problem still remains. Up 'til now the best approach was one first offered by Neil Rubenking of PC Magazine (US) that renamed a copy of the little used or understood DOS utility, LOADFIX.COM, to ENTER.COM. Ted Davis documents this approach in his web book at http://www.maem.umr.edu/~batch/. I'ld like to offer another approach, that can be done entirely with COMMAND.COM and its internal command set.
The approach first occurred to me while working with my ANSI.BAT routine, but I have since seen it documented elsewhere. Regretably, I've lost the reference (Honest!). However, I believe I have some extensions that make the approach a little more robust and more widely applicable than the version I saw.
| Creating a DoList Procedure |
Fundamentally, the idea is to prefix each line in the file with a useful bit of text. Something that can be used to repeatedly invoke a batch procedure that processes the text. I propose using the PROMPT command, run under a secondary command processor, to do this. At its heart, the list is passed through the secondary command processor with the prompt set to something like ...PROMPT CALL %0 x goto:2nd The output is collected in a temporary batch file. Running this secondary batch does the job.But as can be expected with almost anything done with a batch procedure, it's just not that simple. For example, each line is processed as if it were a command issued from the command prompt. That means it is almost certain to illicit a "Bad command or file name" error message. However, worse things happen when the first word on a line of text does name an executable procedure or internal DOS command.
With these pitfalls in mind, the general procedure, DoList.BAT, creates a dummy directory, makes it the active directory, temporarily deletes the path, turns off the console output and runs from within this confined environment just long enough to create the desired secondary procedure.
|
:: DOLIST.BAT - A file to process a list from a text file. Text should :: not contain strings matching internal DOS commands. |
The first input argument names the file to be processed. The second must be a closing parenthesis, i.e. a ')'. An optional command with its control switches follow. If no command is given, ECHO is assumed.The command specified by the third input string can be another batch procedure, DOS command or other program. The text strings on each line in the file cannot exceed 10 items and normal character command line length restriction (127 DOS / 250 Win95) applies to the sum of the command line inputs and the file text.
| A DoList Example Application |
To illustrate DoList.BAT in action, I offer this solution to the problem of changing file name by adding prefixed characters. This is a question that was asked several times recently in the alt.msdos.batch newsgroup. For example, assume the following list of files are to be renamed with a preceeding string of 'Test':ACase.txt BCase.bat CCase.doc DCase.exe Note that there is a way to do this using the FOR command when the names are in an 8.3, 'short' form, i.e. ...for %%v in (?case.*) do ren %%v test%%v But I have found no way to do this with long file names in Windows 95 without processing a list. A list of long filenames is easily created with a DIR /B statement, but using that list in a non-Win NT environment is generally problematic. DoList can be applied to perform the renaming thus ...@echo off dir ?Case.* /b > {t}.txt echo ren %%1 Test%%1 > {t}.bat call DoList {t}.txt ) {t}.bat del {t}.*
| Some Known Caveats |
As with nearly every other batch procedure, this approach cannot correctly handle redirection characters (< and >), the pipe character (|) and command line delimiters. Redirection and pipe characters will cause erroneous operations while all delimiters will be processed as if they were a single space.There is one other situation that I know of that causes significant problems. That is when the first word on the line of text matches a word reserved as an internal COMMAND.COM statement. Most noteable are DATE and TIME, which will hang the process - irretrievably except for the addition of the <CON added to the %COMSPEC% line to re-enable the Control-Break. Otherwise, the CTTY NUL used to suppress error messages generated in list processing also suspends all keyboard entry. In general, perform specific tests if reserved words are to be expected in the list to assure proper operation. I haven't had time to do exhaustive testing on this issue.
One way I have found to minimize the adverse effects of processing lists with internal commands in them is to filter the output from the %COMSPEC% line using FIND. I didn't include this in DoList.BAT to avoid using an external utility and to speed the processing a bit. However, if filtering is desired, I would change the letter 'x' on the 'ECHO @PROMPT ...' line to a pair of dollar signs (%0 $$ goto:2nd=) and change the %COMSPEC% line to read ...
> (b).bat %comspec% /c (a).bat < con | find " $ " This will not solve the problem with DATE and TIME, but will allow processing of nearly all the rest of the internal command words.