This fascinating post:
How is this command legal ? “> file1 < file2 cat”
highlights surprising behavior in a seemingly malformed cat
call to "the shell" (a Linux shell, presumably BASH). Basically, shells seem to be able to grab executables from ambiguous positions within in a series of strings and then use I/O redirection to streams / file descriptors.
The basic process per my understanding is:
- Look for redirection patterns and read them into or out of appropriate streams / file descriptors (examples:
1>
(stdout)) (This occurs prior to starting the executable process in the command! (e.g. thecat
call)) - Find an executable process in the list of strings.
- Start that executable process
- Pause for process completion or continue (as needed) based kinds of output detected in step 1.
This leads to some surprising logic. For instance in a new directory after executing echo "dog" > cat
:
<cat cat >dog
: writes "dog" from filecat
todog
using shell toolcat
<cat cat> cat cat
: overwrites first command, leaving a blankcat
file (not sure what happens in the middle of the second command).<cat cat> cat cat >dog 2>more
: creates empty filesdog
andmore
, overwritescat
file with empty file.<cat >dog cat cat <dog >cat
(creates empty filedog
, overwritescat
w/ empty file)<cat cat >dog 2>much 1>more
: overwritescat
w/ an empty file; creates filesdog
/more
each of which contain the string "dog", creates emptymuch
(The above list behavior was tested on BASH
(v4.3.46).)
Now at some point the poor shell decides it's had enough. For example, when faced with:
<cat dog> cat cat >dog >cat
It complains:
bash: dog: command not found
But there's an extra surprise -- the command actually partially completed. As in most of the above examples it's overwritten the file cat
with a blank file and also created a blank file dog
.
To better understand complex I/O redirection handling in the "most popular Linux shells" and CMD (the standard Windows shell):
BASH
(Linux)TCSH
(Linux)KSH
(Linux)ZSH
(Linux)CMD
(Windows)
... is this kind of order-ambiguous I/O redirection parsing...
- Supported by all of them? (I've only had time to test
BASH
(Linux) andcmd
(Windows).) - Does it support all executables supported or just core shell utilities?
- What are the rules used by these shells to handle sanitization/ordering of the streams/descriptors, particularly when parsing commands where the redirections appear ambiguous based upon the choice of substring (ex.
stuff.dat>1test.dat<2test.dat
where1test.dat
and2test.dat
are files) - To what degree are their parsing rules consistent between shells?
- What determines failure of a command with complex I/O redirection patterns in these shells?