Don't let pathname spaces mess up your scripts
I've lost count of how many times I've written a script only to have someone complain that it doesn't work properly. Often, the culprit turns out to be spaces in utility file paths or script input and output file paths. The following reader questions illustrate several common problem scenarios, and the answers can help your scripts clear the same hurdles. One answer even shows you how to create a small utility that you can use to convert file paths to their 8.3 formats on the fly.
I use the For command to read in lines from input files. Occasionally the pathnames to these input files include spaces, which cause the command to fail. I've tried putting double quotes ("") around the pathnames, but that doesn't seem to help. How do I handle these situations? Should I use a different command?
The For command is the proper command-shell means to read in values from a file and make those values available for processing inside your scripts. Although using double quotes to enclose a pathname that includes spaces is a standard solution, that method alone won't work with the For command.
Until Windows 2000, the For command didn't support spaces in pathnames to an input file. If you try to specify such a path—for example, C:\My Files\Server list.txt—the code fails. If you surround the pathname in double quotes, as you did, the code still fails because the double quotes signify that the contents are to be parsed as a string rather than as a file path. The only way to achieve success in these situations is to convert the pathname to the 8.3 format. For example, C:\My Files\Server list.txt would become C:\MYFILE~1\SERVER~1.TXT.
On systems running Win2K and later, the For command offers the usebackq parsing option, which you can use to solve the space problem. Simply use this option as the sample code in Listing 1 shows. For more information about the For command and the usebackq option, run
at a command prompt to view the For command's Help file. For more advice about dealing with space problems in the For command, see the Web-exclusive article "Two Tricks for Your Scripting Toolbelt," April 2003, InstantDoc ID 38418.
I'm trying to script a registry query that uses reg.exe. The script works with some queries but not others. What's going on?
Using double quotes might not solve all your problems when trying to launch a utility from inside a For command. Several Windows utilities—including reg.exe, which is commonly used for reading and modifying registry settings—typically require the use of a second set of double quotes in the command when arguments being fed to the command contain spaces. These tools might work well when run on their own but fail when embedded in a For command. The most likely cause of your problem is that the path to reg.exe includes a space and you've enclosed this pathname in double quotes, or you might be using double quotes to encapsulate the utility path out of habit or best practice.
Figure 1 shows a basic reg.exe query. Note that a set of double quotes is required around the utility path because of the space in that pathname. Run in and of itself, this command will succeed. But insert the command directly into a For command, as the example in Figure 2 shows, and you'll observe a failure that returns an unrecognized-command error message. Switching the utility pathname to the 8.3 format and removing the double quotes around that pathname, as the sample code in Listing 2 does, fixes the problem.
So, to fix your problem on a continuing basis, you either need to make sure that you don't use double quotes around utility paths and that none of your utility paths include spaces in the pathname, or else use the 8.3 format for all the utility paths in your scripts. Since the release of the Microsoft Windows 2000 Server Resource Kit, Microsoft uses spaces in the default paths to its resource kit tools and Support Tools, so keeping spaces out of utility paths would be difficult. And if you deal with scripts that are going to be distributed to other sites or administrators, you're going to have a hard time anticipating whether their utility paths contain spaces. Therefore, the 8.3 naming solution sounds like the best option. But who wants the hassle of converting all your utility paths to the 8.3 format? You need some code that you can use to convert utility pathnames on the fly.
The first brainstorm I had was to use the Dir command with the /X switch to get the 8.3 filename. This method works, but only for the filename or for a single folder name—not for the entire pathname.
My second idea was to use the Call command and its batch parameters-substitution capability. I came up with the sample Call command code in Listing 3; use the command
to access the Call command's online Help file for a detailed explanation of the command's options.
This method translated the entire folder path into the correct 8.3 format. However, I wanted to tighten up the code. I determined that the For command supports batch substitution parameters similar to the Call command, so I could eliminate the Call portion of the code. I ended up with the sample code in Listing 4; refer to the For command's Help file for more options.
Finally, I combined the code in Listing 4 with the reg.exe code to create the sample code that Listing 5 shows. You should be able to modify this code to solve your problem.
I'm distributing some scripts to junior administrators at our remote campuses. I try to bulletproof the scripts, but the administrators always seem to have problems getting the scripts to work, configuring the input and output file locations, and configuring the location of some resource kit utilities. I'm sure that at least some of the problems relate to spaces in the file pathnames that these folks are using. Is there a better way for me to prepare these scripts?
Yes. Always assume that the distributed scripts will have to deal with space-filled input, output, and resource file pathnames, in spite of any cautions or instructions you provide.
I've found that the best solution is to make any distributed script self-configure the location of input and output files, with the assumption that the script will reside in the same folder as these files and as the executable files for resource kit tools and third-party utilities. When I send a script, I also forward sample input and output files as well as any utilities the script uses, if appropriate. I instruct the script recipients to put all these files in one folder (which can have any name and be in any location they want) and to use the same filenames as the samples use. This way, I can provide a simple list of instructions, and the recipients don't need to edit the scripts—something that can introduce problems.
But as you know, despite all precautions, spaces in the path to the script itself can cause problems. I recommend that you use a variation of the procedure I described earlier to capture the location of the script and convert it to the 8.3 format. In this instance, I'd use a combination of the Call and For commands because the Call command strips off the script filename more consistently than the For command does. Put the SelfLocatingCode.bat code snippet, which Web Listing 1 (http://www.windowsitpro.com/windowsscripting, InstantDoc ID 43996) shows, at the top of your scripts. (For more information about SelfLocatingCode.bat and the other scripts in this article, see the sidebar "How to Use the Scripts.") This code will figure out the script's location, then give you variables to use for the paths to the input and output files as well as the name of the directory containing the tools or utilities that the script depends on. This way, the junior administrators can put your scripts anywhere; as long as the scripts' required file and utility resources are in the same folder, your problem should be solved.
Is there a utility or command that I can use to quickly convert long filenames and pathnames to the 8.3 format and, if possible, enter the result into the clipboard so that I can insert the reformatted names as needed?
I'm unaware of such a tool, but with some creative coding you can make your own. First, use the code that Web Listing 2 shows to create the 8.3Convertor.bat script. Save the file to a location in which you save other tools. To get the clipboard capability you want, be sure clip.exe (a Win2K resource kit tool) is in the path so that the script will find it when run. Then, create a shortcut to 8.3Convertor.bat in your C:\Documents and Settings\username\SendTo folder.
Right-click the file or folder whose name you want to convert to the 8.3 format and select Send To from the context menu. The shortcut that you created to the 8.3Convertor.bat script will be in the list of choices. Selecting that shortcut will open a small command-shell window that displays the filename. The code also loads the 8.3 path into the clipboard so that you can paste it into a command-shell window or the Run dialog box.
I need to write log files to a location whose pathname includes spaces. Some lines of code are writing to the output file but others aren't. Why is that?
Writing to an output file whose pathname includes spaces is the easiest space-problem scenario to solve, but it can be frustrating to diagnose because its only symptom is an output file that isn't created or appended.
The example that Figure 3 shows will fail because of the spaces in the output file path. Typically, encapsulating the output file path in double quotes will solve the problem. Or, you can put double quotes around the output file variable, as the code in Listing 6 does.
If some files write out correctly and others fail, you've probably put double quotes around some of your Echo statements and not others. Run a global search through the entire script, looking for the variable you use for the output file location, and verify that every instance of the variable is surrounded by quotation marks.
I have an error that's driving me crazy. I'm echoing some disk-utilization numbers to an output file, and the completed report includes a trailing space behind each number. I can't figure out where these spaces are coming from. They aren't in my disk-utilization code—they just magically appear after I echo the results to the log file. I've put double quotes around my log filename, right up against the filename. What am I doing wrong?
As you know, space behind your data can be echoed and cause the problem you describe. For example,
Echo Data5 >"C:\My Files\outputlog.txt"
would add a trailing space because of the space between Data5 and the > redirection symbol. But you've confirmed that no spaces are between the data to be echoed and the > redirection symbol, so you can rule out that problem.
I'm guessing that you have a more cryptic problem: a trailing space after the output file's name. You might not think a space in that position would make any difference, but such spaces can cause the error you describe. For example,
Echo Data5>"C:\My Files\outputlog.txt"~
in which the tilde (~) represents a space, produces the error you observe. If you want to test this behavior, place several spaces directly after the closing quotation mark and observe the creation of spaces in the output file. To solve the problem, I recommend you go through all your Echo statements and put a carriage return immediately after the final double quote that encloses the Echo target-file pathname.
Don't Space Out
"Friendly" file and folder names that include spaces are here to stay, so your code needs to be able to handle them. I hope the ideas, code snippets, and scripts in this article will help you to do just that.