0

Why I can't do something like:

tail -n 5 small.txt | diff small.txt

I want to pass the execution result of the first command like second argument of the second, not stand alone input. How can I do it?

2

Try tail -n 5 small.txt | diff small.txt -.

From man diff:

If a FILE is '-', read standard input.

The - method shows you how to do correctly what you wanted to do. But the method below teaches you something that will make your (shell) life easier:

diff small.txt <(tail -n 5 small.txt)
  • Oh, thanks! What is the name of this technique? – stand alone Feb 15 '18 at 8:50
  • from diff manual.. FILES are 'FILE1 FILE2' or 'DIR1 DIR2' or 'DIR FILE...' or 'FILE... DIR'. If --from-file or --to-file is given, there are no restrictions on FILE(s). If a FILE is '-', read standard input. Exit status is 0 if inputs are the same, 1 if different, 2 if trouble. – Kamaraj Feb 15 '18 at 8:54
  • @argle It is buried deep at the end of the man page. – Rui F Ribeiro Feb 15 '18 at 9:00
  • I also noticed that it works well with cat: echo 'one' | cat small.txt -. Maybe it's not only diff feature? – stand alone Feb 15 '18 at 9:05
5

Try this...

  diff small.txt <(tail -n 5 small.txt)
  • 2
    Voting for this one for using process substitution :) – Jordi Feb 15 '18 at 8:57
1

The reason you can't write the pipeline in the way you suggest is that the diff utility expects two input files on the command line and won't by default read from its standard input stream (the output from tail).

You may instruct diff to read from standard input by just adding - as second "file" argument (or first, depending on what order you want to compare the files in):

tail -n 5 small.txt | diff small.txt -

diff will detect the - filename and read from the tail command instead of from a second file. This is semantics implemented by a few utilities such as diff, cat, paste, etc. but is not universal (the shell doesn't know about - "being the same as standard input").

In bash and other shells that supports process substitution using <( ... ), one may instruct the shell to create a temporary file (or FIFO) that contains the output from a particular command:

diff small.txt <( tail -n 5 small.txt )

This is essentially (but not technically) the same as

tail -n 5 small.txt >tmpfile
diff small.txt tmpfile
rm -f tmpfile

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.