I try to write sort of a 'file watcher' that regularly processes all new files in a directory since last run. I started it with the use of CoPilot and it comes up with the very handy dos-command 'forfiles'.
However, the code requires to prepare a string to pass to the command line via 'exec' in TCL. If I take that string to the command line by hand, it works. If I pass it to exec I receive an exception:
child process exited abnormally
while executing
"exec cmd.exe /c $cmdStr"
(procedure "watchFiles" line 5)
invoked from within
"watchFiles "d:\\zz\\" "*.txt""
("try" body line 2) CHILDSTATUS 19656 1
Here is the most stripped down code, to reproduce the problem. The 'puts' after generating the line to pass to exec is exactly the line, that works on the command line directly. Note: Whatever directory and filepattern you may try, make sure there is at least one file of the searched type with a timestamp of today, or there will be no results even on command line.
console show
proc watchFiles {watchDir filePattern} {
set watchDir [file nativename [file normalize $watchDir]]
set cmdStr "forfiles /p \"$watchDir\" /m $filePattern /d +0 /c \"cmd /c echo @fdate @ftime @relpath\""
puts "$cmdStr"
set output [split [exec cmd.exe /c $cmdStr] "\n"]
after 10000 [list watchFiles $watchDir $filePattern]
}
try {
watchFiles "d:\\zz\\" "*.txt"
} on error {msg} {
puts stderr "$msg $::errorInfo $::errorCode"
}
1 Answer 1
The problem arises due to the fact, that the TCL exec tries to pass each argument to its called program. The exec does quoting on its own. Due to that, it is not wise to pass all arguments as one to the exec call.
What I do is to eventually write a temporary batch file and issue the commands there.
In addition, there is a magic autoexec_ok function, which may also help.
In a nutshell:
Don't try to quote on your own
Pass arguments one by one
aMike has already commented this.
Please look to this page for the full problem and solution possibilities: TCL wiki:exec quotes problem
stderr. Check if theoutputvariable has more clues.