-   Programming (
-   -   how to use pipe (|) in a one-line bash command (

gstt 10-06-2010 02:25 PM

how to use pipe (|) in a one-line bash command
I am writing a script to put a bunch of files in each subdirectory in a .tar.gz. Here is what I have right now:

for a in `ls -d */`;
echo $a;
f1=`find $a -regex '.*ABC' | xargs echo`;
f2=`find $a -regex '.*DEF' | xargs echo`;
f="$f1 $f2";
echo $f;
tar czvf $a.tar.gz $f

But I don't know how to put this script into a one-line bash script. I think my major question is about "|" in the one-line script. Could anyone help me with this?

GrapefruiTgirl 10-06-2010 02:34 PM

Your question is a little bit confusing in that the pipe doesn't have much to do with whether or not this script is a one-liner or a 10-liner. You can put all that code on a single line, provided that individual commands are separated appropriately with semicolons like they are. But the two pipes you are currently using, will still be doing the same thing they do now; they pipe the output from `find` into `xargs`.

I figure that your whole command could be shortened a little bit somehow, perhaps by using only `find` rather than using the loop with `ls`, and maybe other change(s), but please explain a little more what exactly you wish to do? Note that jamming some code down into one line doesn't necessarily make it better ;) but can make it harder to figure out what the code does!

gstt 10-06-2010 02:50 PM

Yes. You are absolutely right. On a second try, I found there is nothing wrong to put | in a line, as in my previous script.

At first, I am worried about what is the scope of command as the input to the pipe. For example

ls d1; ls d2 | xargs echo;

From what I tested, only ls d2 is input to xargs echo.

So I think my following question now is if there is syntax to set several commands as input to the pipe. For example, like here, I want to put the output of ls d1 and ls d2 to the pipe of xargs echo.


GrapefruiTgirl 10-06-2010 03:05 PM

To my understanding/knowledge, you cannot pipe two individual processes into one pipe. You could make a FIFO or something of this nature, and send data into from several sources, and retrieve the data using a single process. The data would come out of the FIFO (of course) in the same way it went in; i.e. if it went in scrambled, it would come out scrambled.

Perhaps this might interest you:

for a in `ls -d */`; do
  f1=`find $a -regex '.*ABC'
  f2=`find $a -regex '.*DEF'
  f="$f1 $f2";
  echo $f;
done; | xargs -I {} tar czvf $a.tar.gz {}

Note that this code is still a little convolved, and I don't totally get what exactly you're trying to do. And, this code as it's written, may not even work - I just stuck it together to show that you can output the results of the entire contents of the code inside the loop, through a pipe into a different command.

A simpler demo:

for x in 2 3 4; do
    echo $x
    echo $((x+3))
done | xargs -I {} echo "hello, the number is {}"

Again, just a demonstration concept - it doesn't do anything useful.

ghostdog74 10-06-2010 07:54 PM


tar zcvf filename.tgz --recursion *ABC *DEF

All times are GMT -5. The time now is 11:26 AM.