I am currently trying to make a script that creates bytes that will be piped as input to netcat.
Here is the idea of the script:
(perl -e "print \"$BYTES\x00\";
cat file;
perl -e "print \"More bytes\"x16 . \"\r\n\"";) | netcat ip port
I tried using both using a subshell and command substitution (ex. with $()) to execute the commands. However I fail to understand why the output of the script when using command substitution is wrong. I suspect that command substitution incorrectly pipes its output when executing multiple commands. Can someone explain to me why this is so?
EDIT
Here is the variant that used command substitution:
$(perl -e "print \"$BYTES\x00\";
cat file;
perl -e "print \"More bytes\"x16 . \"\r\n\"";) | netcat ip port
Best Answer
Okay, let's break this down. A subshell executes its contents in a chain (i.e., it groups them). This actually makes intuitive sense as a subshell is created simply by surrounding the chain of commands with
()
. But, aside from the contents of the subshell being grouped together in execution, you can still use a subshell as if it were a single command. That is, a subshell still has anstdin
,stdout
andstderr
so you can pipe things to and from a subshell.On the other hand, command substitution is not the same thing as simply chaining commands together. Rather, command substitution is meant to act a bit like a variable access but with a function call. Variables, unlike commands, do not have the standard file descriptors so you cannot pipe anything to or from a variable (generally speaking), and the same is true of command substitutions.
To try to make this more clear, what follows are a set of maybe-unclear (but accurate) examples and a set of, what I think may be, more easily-understood examples.
Let's say the
date -u
command gives the following:But, we want to manipulate the output of this command. So, let's pipe it into something like
sed
:Wow, that was fun! The following is completely equivalent to above (barring some environment differences that you can read about in the man pages about your shell):
That should be no surprise since all we did was group
date -u
. However, if we do the following, we are going to get something that may seem a bit odd at first:This is because
$(date -u)
is equivalent to typing out exactly whatdate -u
outputs. So the above is equivalent to the following:Which will, of course, error out because
Thu
is not a command (at least not one I know of); and it certainly doesn't pipe anything tostdout
(sosed
will never get any input).But, since we know that command substitutions act like variables, we can easily fix this problem because we know how to pipe the value of a variable into another command:
But, as with any variable in bash, you should probably quote command substitutions with
""
.Now, for the perhaps-simpler example; consider the following:
I am not sure how to describe it any simpler than that. The command substitution works just like a variable access where the subshell still operates like a command.