0

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"
}
jonrsharpe
123k31 gold badges278 silver badges489 bronze badges
asked Oct 4, 2025 at 10:32
4
  • Only to explain the thought behind this. How to do that in TCL with the least overhead possible? forfiles uses ntfs-tables to produce its results. Thereafter I only need to further filter by making use of the timestamp values the 'echos' created in the forfiles statement. And that can be done by regexp'ing these strings. Meaning: There is almost no hardware intervention nessecary, just memory work (file mTime uses 'stats' which is hardware and therefore should be 'slow'). Thats the theory, but I'm still stuck with the 'exec' :) Commented Oct 4, 2025 at 10:41
  • 1
    I'm guessing the exit code is set without writing to stderr. Check if the output variable has more clues. Commented Oct 4, 2025 at 12:40
  • @Donal Fellows: Thanks for your response. I do not receive the contents of output due to the former exception. I already tried '-ignorestderr' while calling exec to no avail. I have no more information so far, please feel free to ask, if you need more details. Commented Oct 7, 2025 at 9:12
  • From the 'exec' man page: "each arg becomes one word of a command", so I think your "$cmdstr" is wrong. Perhaps if you splat it out: "{*}$cmdstr" to make each word become a separate command argument. HTH. Commented Oct 14, 2025 at 17:39

1 Answer 1

0

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

answered Oct 23, 2025 at 12:10
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.