13 September 2010

Name Log Files in a Consistent Format

I expect developers to program like I do, which didn't happen this week.

The task is to concatenate log files in a folder into a single file to import into a database. The Windows command to do the job is for /f %a in ('dir /b *.csv') do type %a >> dest.csv. (dir /b lists entries in a folder without any heading.) While testing using echo in place of type, I noticed that due to the way dir sorts file, the script would concatenate log files in this order: Log-02.csv, Log-03.csv, ..., Log.csv i.e. the first log file last. This order seems to correspond with the characters in the ASCII table.

(Aside: Windows Explorer lists Log.csv first because Explorer doesn't use ASCII sort order.)

Of course, just to get the job done, the work-around is to rename Log.csv to Log-01.csv before running the script.

It threw me that developers wouldn't name log files consistently.

10 September 2010

SetLocal EnableDelayedExpansion in CMD Scripts

In a Windows CMD for loop, variables within the loop aren't, by default, resolved into a value for every iteration of the loop. Here's a script that should list all files in a folder.

@echo off
for /f %%a in (*) do (
  set test=%%a
  echo %test%

However, when you run the script, only the first file found is output (the variable test is only set in the first iteration of the loop). Turns out that I'm the n'th generation of CMD programmers to trip over this issue. It seems that CMD only processes the for (...) statement once, so the variable test is only set once. To get CMD to reprocess your variable in each iteration, put your code into a setlocal EnableDelayedExpansion ... endlocal block and delimit with exclamation marks any variables that CMD should reprocess in each iteration of the loop (hence the unintuitive name of the block).

@echo off
setlocal EnableDelayedExpansion
for %%a in (*) do (
  set test=%%a
  echo test=!test!

I couldn't find an official MS documentation of EnableDelayedExpansion or the use exclamation marks for variables.