Piping commands after a piped xargs

You are almost there. In your last command, you can use -I to do the ls correctly

-I replace-str

    Replace occurrences of replace-str in the initial-arguments with names read from standard input.  Also, unquoted blanks do not terminate input items; instead the separator is the newline character.  Implies -x and -L 1.

So, with

find . -type d -name "*log*" | xargs -I {} sh -c "echo {}; ls -la {} | tail -2"

you will echo the dir found by find, then do the ls | tail on it.


GNU Parallel makes this kind of tasks easy:

find . -type d -name "*log*" | parallel --tag "ls -la {} | tail -2"

If you do not want to do a full install of GNU Parallel you can do a minimal installation: http://git.savannah.gnu.org/cgit/parallel.git/tree/README


Just in addition to fredtantini and as a general clarification (since the docs are a bit confusing):

The xargs -I {} will take the '{}' characters from the standard input and replace them with whatever comes in from the pipe. This means you could actually replace {} with any character combination (maybe to better suite your preferred programming flavor). For example: xargs -I % sh -c "echo %". If you always use the xargs -I {} you can replace it with xargs -i as it is the shorthand. EDIT: The xargs -i option has been deprecated, so stick to the xargs -I{}.

The sh -c will tell your bash/shell to read the next command from a string and not from the standard input. So writing sh -c "echo something" is equivalent to echo something.

The xargs -I {} sh -c "echo {}" will read the input you created with sh -c which is echo {}. Since you told it to replace {} with the arguments you got from the pipe, that's what will happen.

You can easily test this even without piping, just type the above command in a terminal. Whatever you write next will get outputted to the terminal (Ctrl-D to exit).

In the ls -la {} command the same thing happens again. The {} is replaced with the contents of the pre-pipe command.