Give the Windows For command more power by incorporating SFU commands
Windows Services for UNIX (SFU) includes UNIX and Linux binaries that you can run from a Windows command line or in a batch file. Installing SFU is easy, and you get a host of new commands that don’t exist in Windows. When you combine the SFU commands with the Windows For command, you can create powerful tools.
I found this out firsthand recently. I wanted to email myself the log file from each nightly NTBackup job so I could check it. Because the log files’ names are the dates on which the backups ran, I knew that I could use the command
Dir *.log /o:-d
in the C:\Documents and Settings\Administrator Local Settings\Application Data\Microsoft Windows NT\NTBackup\Data directory to get a list of the log files’ pathnames, sorted with the newest log file first. However, I needed to extract the filename from the most recent log file’s pathname. The Windows For command can’t do that on its own. What I needed was a command to read the Dir command’s output, find the line containing the current date, and extract the filename so that the file could be emailed to me.
I initially thought of using the SFU grep command to extract the filename. Like the Windows Find command, the SFU grep command finds lines in a text file containing a specified string. However, there’s an even better tool: the SFU find command. You can use the SFU find command to find files that meet certain criteria, then perform operations on those files.
Using the SFU find command and the Windows For command, I came up with the command sequence
For /f "usebackq" %%T in (`c:\SFU\common\find . -ctime 0 -name "*.log"`) Do Set fn=%%T
(Although the command appears on several lines here, you’d enter it on one line in a batch file.) Since you might not be familiar with the SFU find command, let’s walk through it. To use the SFU find command from a Windows batch file, you first need to call the command by specifying its pathname. If you install SFU in the default location, the SFU commands are in two directories: C:\SFU\common and C:\SFU bin. The files in the common directory have an .exe extension, whereas the files in the bin directory don’t. For Windows, you use the files in the common directory.
The SFU find command, which is case sensitive like all the SFU commands, can take up to three parameters. The first parameter specifies the location to search. In this case, I wanted to search the current directory and its subdirectories, so I specified a period. The second parameter provides the criteria the files must meet to be included in the result set. In my case, I had two criteria:
• The files’ last modification date needed to be the current date. I used the -ctime option followed by a 0 to specify that I wanted to find files in which the last status change was 0 days ago.
• The files’ extensions had to be .log. I used the -name option followed by “*.log” to indicate that I wanted only log files. The quotes are necessary to stop the pre-expansion of the * wildcard by the Windows command shell.
The SFU find command has an optional third parameter, which you use to specify the operation to perform on the files that meet the criteria. In my case, I didn’t include this parameter. Note that there are many parameters and options you can use with the SFU find command. Unfortunately, this command’s online documentation isn’t as helpful as it could be, but you can find a good overview of this command at linuxmanpages.com/man1/find.1.php.
There are some items in the Windows For command portion of the command sequence that are worth pointing out. First, note the use of the usebackq option with the /f parameter. When you use this option, the Windows command shell interprets any text enclosed in back ticks (`) as commands to execute, which in turn allows quotes inside the command.
Also note the double percent signs (%%). When you use an iterative variable (in this case, %%T) in a Windows For command that you execute in a batch file, you need to use a double percent sign. The %%T variable stores the filename that the SFU find command returns. This filename is then set to the fn variable. In the batch file I created, I use Blat and the filename in the fn variable to email the file to myself. (Blat is a free command-line email program at www.blat.net.)
I also used the SFU find and Windows For commands together to solve a similar problem. I wanted to create a batch file that not only sent daily database backup files to an offsite ftp server for storage but also emailed the results of this operation to me so I’d know whether it was successful. To email those daily results, I needed a command to get the current date and extract portions of that date. Using the SFU find command and the Windows For command, I came up with the command sequence
For /f "usebackq tokens=1,2,3" %%T in (`c:\SFU\common\date +"%%A %%m%%d %%d/%%m/%%Y"`) Do Set dow=%%T & Set dom=%%U & Set today=%%V
(Although the command appears on several lines here, you’d enter it on one line in a batch file.)
As you can see, this command sequence uses the SFU date command. You can use this command to obtain the current time in a given format or set the system date. In this case, I use it to obtain the current time. The + sign after the command pathname signals the start of a formatting string that specifies the parts of the date to be returned by the SFU date command and how those parts should be formatted. Each format option begins with a % sign (%% in a batch file). If you specify two options with no space between them, the Windows For command treats the output from the two options as one string. If you separate the two options with a space, the Windows For command treats the output from each option as a separate string, which enables you to assign them to separate variables. In this case, the SFU date command returns three separate strings:
• The %%A option tells SFU to return the full weekday name (e.g., Sunday). The Windows For command assigns this string to the dow variable.
• The %%m%%d option tells SFU to return the month and day of the month in the format mmdd. This string is assigned to the dom variable.
• The %%d/%%m/%%Y option tells SFU to return full date in the British format dd/ mm/yyyy. This string is assigned to the today variable.
These format options are only a few of the many options available. You can see all the
options by typing
in SFU. In the Windows For command portion of the command sequence, note the tokens=1,2,3 option with the /f parameter. This option tells the Windows command processor to retrieve the first three strings (i.e., tokens) returned by the SFU date command. The command processor assumes you’re using a space or tab as the delimiter. If you want to use another character (e.g., a comma) as a delimiter, you need to include the delims= option with the /f parameter.
The batch file in which I used the second command sequence contains another example of how to use the SFU find and Windows For commands together. You can download that batch file by clicking the Download the Code Here button.
I hope these examples give you food for thought about using SFU commands with Windows commands. You can download SFU at technet.microsoft.com/en-us/interopmigration/bb380242.aspx. (You can also get the UNIX and Linux binaries at Cygwin—www.cygwin.com.) Before you install SFU, you need to create two files—passwd and group—and place them in the \%SystemRoot%\System32\drivers etc folder. You don’t need to populate these files because you aren’t fully using SFU; you’re using only the UNIX and Linux binaries. For more information on how to install SFU, see the Windows Services for UNIX web page at technet.microsoft.com/en-us/interopmigration/bb380242.aspx.