Previous | Index | Next

Master 512 Forum by Robin Burton
Beebug Vol. 10 No. 5 October 1991

This month let's tidy up a few 'left-overs' from the last two issues. In spite of the fact that each of those Forums was slightly extended some relevant points weren't covered.

You might have been surprised by what can be done in a short batch file, but this month let's consider what can't be done.


Last month's batch files employed some of the less common functions, but even so others remained unused, like 'FOR <variable> IN (set) DO <command>'. This is probably less understood than the functions we've already looked at.

Here's another batch file, similar to the second one last month, but in spite of the much more complex line 3 it does much the same job, though in a subtly different way.

COPY %0.BAT %1
FOR %%F IN (???????) DO COPY %%F %1%%F
IF %1 == D EXIT
COPY %1 %2

Just as before the job is called with a number of parameters, so you can try it out easily by referring to last month's article. As we saw then, parameters are accessed by means of numbers zero to nine preceded by a '%' symbol, while the contents of parameter variables can be changed by the 'SHIFT' command.

General variables (such as %%F above) are specified by two percentage symbols and any single alphanumeric character. Because the contents of these variables are entirely under the control of your commands, rather than being fixed at the stage of command entry, in this case DOS doesn't care what you call them or the order in which they're defined and used. However, the penalty for this freedom is that the only way to set up the contents of general variables is by means of the 'FOR <variable> IN (SET)' construct, which translates roughly to: 'FOR (each value of <variable>) IN (the) (SET)' DO something...

Paraphrasing line 3, it reads "FOR each occurrence of the name '%%F' derived from the set of files defined by (???????) DO the following... COPY the file named in variable %%F to a new file which is to be called %1%%F."

The names indicated by (SET), which by the way is always enclosed in brackets, must evaluate to filenames. These can be specified with or without an extension (or vice-versa for that matter) and any part of the filename and/or extension in (SET) can be hard coded as literals, can include parameters as well as wildcards, or can be any meaningful combination of them.

For example (?%1?%2?ABC.%3Y) could, in the right circumstances, represent a valid (SET). Certainly the expression is valid syntactically so long as the contents of parameters %1 and %2 don't exceed a single character and %3 doesn't exceed two characters in length.

On the face of it then, it looks like 'FOR IN (SET) DO' could be quite a powerful facility, especially when you remember tests like '==', 'SHIFT' (and 'IF EXIST' which we haven't examined recently).

You'll find however, if you try the above batch file, that in practical terms the results are identical to our simpler version last month, where the equivalent to line 3 was:

COPY ??????? %1*

The major difference in this version of the file is that when the third line executes, the 'COPY' command plus the source and destination filenames are interpreted and displayed in full for every file copied. A by-product of this is that the operation will also be slightly slower, though if you did run last month's job you'll know that this point is somewhat academic in this context.

The reason for the difference in operation is fairly subtle and an explanation might not help much, but let's try. It hinges on the fact that the current value of %%F is always fully evaluated before it is used in each command. At all times therefore, %%F represents an explicit value which can refer only to a single file. In other words, the evaluated contents of general variables do not and cannot include wildcards, although the (SET) in which they are defined might very well do so, as we see here.

In consequence, at run time the 'DO' part of the command is issued repeatedly for each interpreted value of %%F, that is, for every file copied, with full and unique source and destination filename supplied every time. One file is copied and that COPY command ends immediately, although it may be re-issued at once by the first part of the line if further evaluation of %%F requires it. In our example here it usually does, and the reason the job is slower is because each fresh COPY command has to locate the (next) source file in the directory all over again.

By contrast, in last month's batch file, the source names in the command consisted literally of wildcards, so only one command was needed for each set of files. Each copy command therefore executed until all qualifying source files had been processed. Because all the files in each set were copied in one command, DOS kept a pointer into the directory of the last file processed, so no search of the directory was needed between the last file copied and the next. Only one search was required for the first file in each set and execution was therefore quicker (I told you it was subtle).


In spite of the complication of 'FOR IN (SET) DO', in my opinion it's difficult to think of realistic situations which require it which can't be catered for just as easily using simpler commands and wildcards (if you can think of any I'd be interested to hear them).

As we saw before, you can test the contents of parameters against hard coded values (or other parameters or a combination), and make decisions based on equality or otherwise. You might hope therefore, that general variables would allow access to the (SET) name last processed, but if so you'd be disappointed.

The only way to 'define' the contents of general variables is the method used above. What's more you can't use them outside the line which defines them. In effect the interpreted variable contents exist only while each 'DO' command is being executed. You can't therefore, as an example, replace line four in the job above by:


It would be useful if this would work, giving the same result as our original test of 'IF %1 == D', but if you try it you'll see it simply doesn't work.

I always think that several batch functions seem distinctly 'unfinished' and that 'FOR IN (SET) DO' is merely an answer looking for a question. This is a pity, because with a bit more effort batch files could have been much more useful. Instead the problems, or more accurately the restrictions of DOS's batch language are, in the event, far too rigid for it to be used as a general purpose vehicle.

Consider! Parameters can be SHIFTed left, but every time you do this you lose the existing %0 value and you can neither save it by any means nor recall it later, since there's no UNSHIFT function. Equally, sometimes it would be useful to be able to say something like:

%%A = %%B or %%A = %1 or even %1 = "ABC"

This looks simple enough, but it can't be done. There are lots of other shortcomings in the batch language which seem glaringly obvious when compared with even the simplest of interpreted languages. You can't nest 'FOR <variable> IN (SET) DO' commands, only one at a time can be active. The (single) command in the 'DO' portion must be contained entirely in the current line, and it may not be conditional. Multiple commands (e.g. several 'DO' lines) therefore can't be used because there's no 'NEXT' to tell each 'FOR' where to end, while 'IF' can't follow `DO' because there's no 'ELSE'.


To be fair, by stretching your imagination a bit you can construct moderately complex operations in batch files. However, you must take extreme care that the files actually do what you expect them to if you're trying to get clever. Complex batch files can be unreliable. You may think I'm being harsh, but try this. Create a few dummy files called FILE1.TST, FILE2.TST and so on. It doesn't matter what they contain and just two or three files will be enough. Then create and run the following batch file:


By the way, you could alternatively take a short cut and issue this as an immediate, manual command. To use general variables in manual commands you should specify them with only one '%' symbol in each variable, like this:


I know this command looks a bit silly, but its purpose is to highlight the command processor's limited intelligence. You can see at once that the 'BCD' on the end of the line is a mistake, but the point is that the command processor can't. It 'thinks' the extra characters make the destination filename different to the source name. They don't of course, because the 'BCD' is completely spurious and has no effect on the names, but try the command and you'll see that it happily copies each of the files in the list to itself!

The destination names will of course include the 'BCD' in the screen display, but this is truncated when the filename is stored on the disc. The assumption (wrong in this case) is that if a command is evaluated and validated by the command processor with no error it must be both sensible and correct.

This command clearly demonstrates that this needn't be true. That's why I warned you to be careful if you get adventurous with batch files, especially using parameters, when the contents of runtime variables may not be obvious. A 'DIR' after the test above will demonstrate that you've no more files than you started with, although every file has been copied.

OK, so this example is harmless and somewhat artificial. However, think of the potential dangers if you expected a batch file to copy real files to new ones, but in the event it didn't? This could be a bit more serious don't you think?

Weighing up the capabilities versus the limitations of batch functions I keep coming back to the thought that with modest extra effort the designers could easily have produced a much more powerful, useful and above all reliable facility. The basic ideas seem fine, but the job looks half finished, as if someone went to lunch and forgot to return to complete it.

This glimpse of what might have been needn't be a permanent frustration, but you'll have to go to outside software suppliers to find a cure. There are several batch file utilities and compilers for DOS systems, all of which were produced because of these shortcomings, bugs and omissions in the standard system.

If you've ever felt frustrated by the limitations of batch files and want to enhance them beyond the facilities offered by the standard implementation you'll find various worthwhile batch file utilities and compilers in shareware at the usual very reasonable prices.


Finally, I have details of a couple more members who would like to hear from other 512 users and have asked for their addresses to be published.

First is:

Mr. C.W. Robertson,

The second is Oliver Debus. Oliver is 19 years old and would like to hear from other 512 users, most especially of course if they also live in Germany, but Oliver's English is excellent so don't let that stop you writing. He tells me the nearest Acorn dealer is 100Km away and deals only in Archimedes systems anyway, so Oliver feels just as cut off as Ron Thompson who I mentioned a few months back. Write to Oliver at:


Previous | Index | Next

About the Master 512 | Bibliography