3

I have been struggling with this issue for a while now and would really appreciate it if someone could clarify it for me . Suppose I am trying to pipe the two commands together. readlink and cat

readlink Command output
$ readlink -f SUService.log
/cygdrive/c/SUService.log

Now if I try something like this (it fails)

$ readlink -f SUService.log | cat

While something like this will work

$ readlink -f SUService.log | xargs cat

I wanted to know why that is ? I have read this post here in which the OP had a similar question and this post which attempts to explain difference between an argument and an input however i still couldnt wrap my head around the accepted answer(s). From what I understand is that readlink returns the result to stdout which is the terminal screen while cat wants an input as argument. This in return prompts me to ask how do I know if the output of a command (such as locate or readlink) can work as an argument or not for the next command ? I have been doing more reading and it turns out i would like to know when I should be using the xarg command ?

2

3 Answers 3

4

your example is rather confused.

You don't normally send just any characters to cat.

You normally send a file to cat.

Nevertheless, when you do send some characters to cat, it prints the characters.

$ echo abc12123 | cat
abc12123

Normally you send a filename to cat

$ cat abc12123
cat: abc12123: No such file or directory

So notice that cat itself, deals differently with funny characters piped to it, vs being passed them as a parameter.

$ cat b.b
textofb.b

$ echo b.b | cat
b.b

$ cat b.b
textofb.b

i'll use a simpler example than yours

$ echo b.b | xargs cat
textofb.b

see it prints the contents of b.b because asdfasdfs | xargs cat, will send the output of asdfasdfs as a parameter to cat.

So

echo b.b | xargs cat   
=  
cat b.b

Whereas echo b.b | cat is not the same as cat b.b

9
  • Is there a way for me to tell if a certain command will send the output as a parameter as well ?
    – MistyD
    Commented Mar 16, 2015 at 20:23
  • @MistyD yeah, echo asdfsd | command, and command asdfasdf, and see what it does. That's easier than reading a long man page which is the other way. but you learn by both trying and reading.
    – barlop
    Commented Mar 16, 2015 at 20:24
  • As for when to use xargs, I suppose, if you have a command, and you can't pipe to it, and you want to send the output of a command to it, and it only takes a parameter, then you could use xargs. or I suppose, command substitution. Personally, I think I may have used xargs once in Windows cmd to allow me to send info from a command, to a batch file(script) I wrote. I couldn't pipe to my batch file but my batch file could take a parameter. windows cmd shell doesn't have substitution so I think I got a copy of xargs and used that.
    – barlop
    Commented Mar 16, 2015 at 20:32
  • cmd has a usage of the 'for' command that can send the output of a command to another command, as a parameter, but the linux solution - xargs is neater looking, and you can get xargs for windows. so that was when I used xargs.
    – barlop
    Commented Mar 16, 2015 at 20:59
  • 1
    @barlop It seems to me that there are two categories of commands here. In one category, cat, just like sed and awk, will accept input from stdin just as it would input from a file named on the command line. In the other category, commands, such as echo, date, and ls, do not use stdin at all.
    – John1024
    Commented Mar 16, 2015 at 21:28
6

The following command does not fail. It simply does something you didn't expect:

readlink -f SUService.log | cat

When cat is given stdin, it copies it to stdout. It does not look for filenames in it.

Alternatively, this will read from the named file:

cat "$(readlink -f SUService.log)"

xargs will also put the name on the cat command line, yielding the same result:

readlink -f SUService.log | xargs cat
2
  • thanks for explaining that but what I am looking for is when would i need to use xarg command ?
    – MistyD
    Commented Mar 16, 2015 at 20:19
  • 2
    Use xargs when you want to use stdin as the arguments on a command line. echo filename | xargs cat is the same as cat filename.
    – John1024
    Commented Mar 16, 2015 at 20:30
2

Take a look at the manpages for cat and xargs to see what they do.

man cat

cat - concatenate files and print on the standard output

And:

man xargs

xargs - build and execute command lines from standard input

Here's a little demo

Let's create a test file:

echo "a" > test
echo "b" >> test
echo "c" >> test

cat

cat test

Reads the file and gives:

a
b
c

echo | cat

echo test | cat

According to man cat, this does the same as:

echo test | cat -

Which pipes test into cat's stdin, and tells cat to read from stdin.

echo | xargs cat

echo test | xargs cat

Generates and executes the following command:

cat test

The output of this we've already shown.

If we run

<test xargs -n1 cat

Xargs sees this on input:

a
b
c

And it generates the following commands:

cat a
cat b
cat c

Which should result in three errors since those files do not exist.

Why the -n1?

According to man xargs, the -n1 tells xargs to use one argument (read from stdin) in each command that it generates.

If we use -n2 instead, we generate the following which uses up to two parameters per command:

cat a b
cat c

And if we use -n3 or higher, or simply omit the -n:

< test xargs cat

We get:

cat a b c

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .