I want to understand the use of xargs man
in Rampion's code:
screen -t man /bin/sh -c 'xargs man || read'
Thanks to Rampion: we do not need cat!
Why do we need xargs
in the command?
I understand the xargs
-part as follows
- cat nothing to xargs
- xargs makes a list of man -commands
I have had an idea that xargs makes a list of commands. For instance,
find . -type f -print0 | xargs -0 grep masi
is the same as a list of commands:
find fileA AND grep masi in it
find fileB AND grep masi in it
and so on for fileC, fileD, ...
No, I don't cat
nothing. I cat whatever input I get after I run the command. cat
is actually extraneous here, so let's ignore it.
xargs man
waits on user input. Which is necessary. Since in the script you grabbed that from, I can't paste in the argument for man until after I create the window. So the command that runs in the window needs to wait for me to give it something, before it tries to run man.
If we just ran screen /bin/sh -d 'man || read'
, it would always complain "What manual page do you want?" since we never told it.
xargs gathers arguments from stdin and executes the command given with those arguments.
so cat is waiting for something to be typed, and then xargs is running man with that input.
xargs is useful if you have a lot of files to process, I often use it with output from find.
xargs will stuff as many arguments as it can onto the command line.
It's great for doing something like
find . -name '*.o' -print | xargs rm
The cat
command does not operate on nothing; it operates on standard input, up until it is told that the input is ended. As Rampion notes, the cat
command is not necessary here, but it is operating on its implicit input (standard input), not on nothing.
The xargs
command reads the output from cat
, and groups the information into arguments to the man
command specified as its (only) argument. When it reaches a limit (configurable on the command line), it will execute the man
command.
The find ... -print0 | xargs -0 ...
idiom deals with file names that contain awkward characters such as blanks, tabs and newlines. The find
command prints each filename followed by an ASCII NUL ('\0'
); this is one of two characters that cannot appear in a simple file name - the other being '/' (which appears in path names, of course, but not in simple file names). It is not directly equivalent to the sequence you provide; xargs
groups collections of file names into a single argument list, up to a size limit. If the names are short enough (they usually are), then there will be fewer executions of grep
than there are file names.
Note, too, the grep
only prints the file name where the material is found if it has more than one file to search -- or if it supports an option so that it always prints the file names and the option is used: '-H
' is a GNU extension to grep
that does this. The portable way to ensure that the file names always appear is to list /dev/null
as the first file (so 'xargs grep something /dev/null
'); it doesn't take long to search /dev/null
.