Passing two arguments to a command using pipes
Solution 1
I think you want 'Process Substitution' http://tldp.org/LDP/abs/html/process-sub.html. It also works on zsh, though it has more options and the syntax may be different.
It creates a pseudo file (/dev/fd/something
) for each substitution. It's pretty useful. The command can only read as a stream, meaning it can not go back and forth with fseek. It needs to read it as a stream of bytes, like a pipe.
Your examples work as process substitution:
cat <(echo abc) <(echo xyz)
paste -d, <(cut -f2 -d, file1) <(cut -f1 -d, file2)
Think of it as a tool to use a process and have it pretend to be a file without any temp files.
(from my earlier answer )
Solution 2
I like xargs As an example I want to find the size of all the mysql data dir under /usr/local
osx:local user$ pwd /usr/local osx:local user$ ls | grep mysql mysql mysql-5.0.51a-osx10.5-x86_64 mysql-5.0.51b-osx10.5-x86_64 mysql-5.1.39-osx10.5-x86_64 mysql-5.6.17-osx10.7-x86_64 os x:local user$ ls | grep mysql |sudo xargs du -sh 4.0K mysql 2.8G mysql-5.0.51a-osx10.5-x86_64 10G mysql-5.0.51b-osx10.5-x86_64 25G mysql-5.1.39-osx10.5-x86_64 753M mysql-5.6.17-osx10.7-x86_64 osx:local user$
Solution 3
The curly braces thingy actually worked because the pipe operator will connect the standard outputs of the grouped commands into the standard input of the third.
You can tell the printout is not from the echos by running any command that does not use standard input, e.g. { echo 1; echo 2;} | echo 3
will print 3 as opposed to 1\n2\n3.
However, this is not the thing you wanted because the two commands in the curly braces are writing to the same output which is like cat
-ing their results. To generate two different results to use as the two arguments for commands like paste
, you'll have to use a temporary file or a named pipe.
You can use mktemp
to generate a unique temporary file or mkfifo
to create a FIFO pipe file.
Related videos on Youtube
goweon
Updated on September 18, 2022Comments
-
goweon over 1 year
Usually, we only need to pass one argument:
echo abc | cat echo abc | cat some_file - echo abc | cat - some_file
Is there a way to pass two arguments? Something like
{echo abc , echo xyz} | cat cat `echo abc` `echo xyz`
I could just store both results in a file first
echo abc > file1 echo xyz > file2 cat file1 file2
But then I might accidentally overwrite a file, which is not ok. This is going into a non-interactive script. Basically, I need a way to pass the results of two arbitrary commands to
cat
without writing to a file.
UPDATE: Sorry, the example masks the problem. While
{ echo abc ; echo xyz ; } | cat
does seem to work, the output is due to theecho
s, not thecat
.A better example would be
{ cut -f2 -d, file1; cut -f1 -d, file2; } | paste -d,
which does not work as expected.With
file1: a,b c,d file2: 1,2 3,4
Expected output is:
b,1 d,3
RESOLVED:
Use process substitution:
cat <(command1) <(command2)
Alternatively, make named pipes using
mkfifo
:mkfifo temp1 mkfifo temp2 command1 > temp1 & command2 > temp2 & cat temp1 temp2
Less elegant and more verbose, but works fine, as long as you make sure temp1 and temp2 don't exist before hand.
-
user606723 almost 13 yearsThis makes me scratch my head. You want to pipe two different commands to a single cat?
-
Ignacio Vazquez-Abrams almost 13 yearsYou do know that "piping" and "arguments" are two completely unrelated concepts, right?
-
goweon almost 13 years@Ignacio err... I'm not that familiar with Linux so I don't really know the difference. I always thought piping meant it takes the previous result as an argument. Care to enlighten me?
-
Rich Homolka almost 13 years@firebat no, pipe means to take the stdout of the previous command as standard input of the next command. You can still have arguments, which are a different concept.
-
Rich Homolka almost 13 yearsalso, as far as your Update text, the output does come from cat, just you want the statements seemed as separate to cat, which it can not do since they are serialized into one stream.
-
-
Admin about 2 yearsWow, really cool! Just what I needed :)