3

If I want to redirect not the stdio but as arguments the output of a program , should I use xargs?

For example, I do ls and I want the filenames to be arguments to the next command rather than an input stream.

Is there a good example of what I'm talking about? This example is superficial but illustrates what I mean: use the output from ls as arguments to cat for displaying the contents of the files.

1 Answers1

3

First, do not parse ls. There are many reliable ways of getting file names but ls is not one of them.

The following uses the shell's globbing to generate file names and passes a nul-separated list of them to xargs which runs them through cat:

printf '%s\0' * | xargs -0 cat

I understand that the point of this was to demonstrate files->xargs. Otherwise, of course, unless there are too files to fit on a command line, the above can be replaced with:

cat *

Being more selective

Both ls and printf '%s\0' * will display all of a directory's contents, including its subdirectories. If you want to be more selective, say, including regular files but not subdirectories, then, as cas suggests, find is better tool:

find . -maxdepth 1 -type f -print0 | xargs -0 cat

Or:

find . -maxdepth 1 -type f -exec cat {} +

find has many useful options. See man find for details.

John1024
  • 74,655
  • 1
    Note that cat * can cause an arguments list too long error. – cuonglm May 28 '16 at 02:59
  • @cuonglm Very true. I updated the answer to mention that case. – John1024 May 28 '16 at 05:24
  • what if I need pass output of ls -t | head -1 to another command? based on your answer, I worked out printf '%s\0' "$(ls -t | head -1)" | xargs -0 gvim (needed the double quotes for filename having spaces).. tested a few cases, but not sure if this can open latest modified file for all sorts of filenames.. – Sundeep May 28 '16 at 05:58
  • @spasic If your file names don't contains any special characters, then try gvim "$(ls -t | head -1)". – John1024 May 28 '16 at 06:23
  • that seems to work even for special characters like space/quotes/newlines, same as the command with xargs.. I think both are equivalent – Sundeep May 28 '16 at 06:52
  • +1. printf "%s\0" * will also output directories, symlinks, device nodes, named pipes and sockets. find . -maxdepth 1 -type f -print0 is better. Use find -L ... if you want to follow symlinks (i.e. treat symlinks to files as if they were files) – cas May 28 '16 at 07:08
  • @cas Very good. I just added two find examples to the answer. – John1024 May 28 '16 at 07:39