How to merge and pipe results from two different commands to single command?
Your magical union thing is a semicolon... and curly braces:
{ cat wordlist.txt ; ls ~/folder/* ; } | wc -l
The curly braces are only grouping the commands together, so that the pipe sign |
affects the combined output.
You can also use parentheses ()
around a command group, which would execute the commands in a subshell. This has a subtle set of differences with curly braces, e.g. try the following out:
cd $HOME/Desktop ; (cd $HOME ; pwd) ; pwd
cd $HOME/Desktop ; { cd $HOME ; pwd ; } ; pwd
You'll see that all environment variables, including the current working directory, are reset after exiting the parenthesis group, but not after exiting the curly-brace group.
As for the semicolon, alternatives include the &&
and ||
signs, which will conditionally execute the second command only if the first is successful or if not, respectively, e.g.
cd $HOME/project && make
ls $HOME/project || echo "Directory not found."
Since wc
accepts a file path as input, you can also use process substitution:
wc -l <(cat wordlist.txt; ls ~/folder/*)
This roughly equivalent to:
echo wordlist.txt > temp
ls ~/folder/* >> temp
wc -l temp
Mind that ls ~/folder/*
also returns the contents of subdirectories if any (due to glob expansion). If you just want to list the contents of ~/folder
, just use ls ~/folder
.
I was asking myself the same question, and ended up writing a short script.
magicalUnionThing
(I call it append
):
#!/bin/sh
cat /dev/stdin
$*
Make that script executable
chmod +x ./magicalUnionThing
Now you do
cat wordlist.txt |./magicalUnionThing ls ~/folder/* | wc -l
What it does:
- Send standard input to standard output
- Execute argument.
$*
returns all arguments as a string. The output of that command goes to script standard output by default.
So the stdout of magicalUnionThing will be its stdin + stdout of the command that is passed as argument.
There are of course simpler ways, as per other answers.
Maybe this alternative can be useful in some cases.