Use:
ls | xargs -t -i{} echo {} 2>&1 >/dev/null
The 2>&1
sends the standard error from xargs
to where standard output is currently going; the >/dev/null
sends the original standard output to /dev/null
. So, the net result is that standard output contains the echo commands, and /dev/null
contains the file names. We can debate about spaces in file names and whether it would be easier to use a sed
script to put 'echo' at the front of each line (with no -t
option), or whether you could use:
ls | xargs -i{} echo echo {}
(Tested: Solaris 10, Korn Shell ; should work on other shells and Unix platforms.)
If you don't mind seeing the inner workings of the commands, I did manage to segregate the error output from xargs
and the error output of the command executed.
al * zzz | xargs -t 2>/tmp/xargs.stderr -i{} ksh -c "ls -dl {} 2>&1"
The (non-standard) command al
lists its arguments one per line:
for arg in "$@"; do echo "$arg"; done
The first redirection (2>/tmp/xargs.stderr
) sends the error output from xargs
to the file /tmp/xargs.stderr
. The command executed is 'ksh -c "ls -dl {} 2>&1"
', which uses the Korn shell to run ls -ld
on the file name with any error output going to standard output.
The output in /tmp/xargs.stderr
looks like:
ksh -c ls -dl x1 2>&1
ksh -c ls -dl x2 2>&1
ksh -c ls -dl xxx 2>&1
ksh -c ls -dl zzz 2>&1
I used 'ls -ld
' in place of echo
to ensure I was testing errors - the files x1
, x2
, and xxx
existed, but zzz
does not.
The output on standard output looked like:
-rw-r--r-- 1 jleffler rd 1020 May 9 13:05 x1
-rw-r--r-- 1 jleffler rd 1069 May 9 13:07 x2
-rw-r--r-- 1 jleffler rd 87 May 9 20:42 xxx
zzz: No such file or directory
When run without the command wrapped in 'ksh -c "..."
', the I/O redirection was passed as an argument to the command ('ls -ld
'), and it therefore reported that it could not find the file '2>&1
'. That is, xargs
did not itself use the shell to do the I/O redirection.
It would be possible to arrange for various other redirections, but the basic problem is that xargs
makes no provision for separating its own error output from that of the commands it executes, so it is hard to do.
The other rather obvious option is to use xargs
to write a shell script, and then have the shell execute it. This is the option I showed before:
ls | xargs -i{} echo echo {} >/tmp/new.script
You can then see the commands with:
cat /tmp/new.script
You can run the commands to discard the errors with:
sh /tmp/new.script 2>/dev/null
And, if you don't want to see the standard output from the commands either, append 1>&2
to the end of the command.