$ date > '< abcd'
$ cat '< abcd'
<something>
$ tclsh8.5
% exec cat {< abcd}
couldn't read file " abcd": no such file or directory
whoops. This is due to the the specification of 'exec'.
If an arg (or pair of args) has one of the forms described below then it is used by exec to control the flow of input and o开发者_如何学JAVAutput among the subprocess(es). Such arguments will not be passed to the subprocess(es). In forms such as “< fileName”, fileName may either be in a separate argument from “<” or in the same argument with no intervening space".
Is there a way to work around this?
Does the value have to be passed as an argument? If not, you can use something like this:
set strToPass "< foo"
exec someProgram << $strToPass
For filenames, you can (almost always) pass the fully qualified name instead. The fully qualified name can be obtained with file normalize
:
exec someProgram [file normalize "< foo"] ;# Odd filename!
But if you need to pass in an argument where <
(or >
) is the first character, you're stuck. The exec
command always consumes such arguments as redirections; unlike with the Unix shell, you can't just use quoting to work around it.
But you can use a helper program. Thus, on Unix you can do this:
exec /bin/sh -c "exec someProgram \"$strToPass\""
(The subprogram just replaces itself with what you want to run passing in the argument you really wanted. You might need to use string map
or regsub
to put backslashes in front of problematic metacharacters.)
On Windows, you have to write a batch file and run that, which has a lot of caveats and nasty side issues, especially for GUI applications.
One simple solution: ensure the word does not begin with the redirection character:
exec cat "./< abcd"
One slightly more complex:
exec sh -c {cat '< abcd'}
# also
set f {< abcd}
exec sh -c "cat '$f'"
This page on the Tcl Wiki talks about the issue a bit.
Have you tried this?
% exec {cat < abcd}
Try:
set myfile "< abcd"
exec cat $myfile
精彩评论