39

I am trying to do something along the lines of:

diff `ls -1a ./dir1` `ls -1a ./dir2`

But that doesn't work for obvious reasons. Is there a better way of achieving this (in 1 line), than this?

ls -1a ./dir1 > lsdir1
ls -1a ./dir2 > lsdir2
diff lsdir1 lsdir2

Thanks

4 Answers 4

62

You were close. In bash you want process substitution, not command substitution:

diff <(ls -1a ./dir1) <(ls -1a ./dir2)
2
  • Process substitution is not necessary, though. The answer below (superuser.com/a/228773/566289) is on point!
    – Jan D
    May 5, 2019 at 12:00
  • 5
    Except that answer diffs the content, not the filenames!
    – lost
    Aug 14, 2019 at 13:14
13
diff -rq dir1 dir2

using the -r option, walk entire directory trees, recursively checking differences between subdirectories and files that occur at comparable points in each tree. The trick is to use the -q option to suppress line-by-line comparisons

5
  • 6
    @festo : You wree missing the poitn of this question, I don't actually want to diff the contents of the files, I want to diff the output of the ls commands
    – bguiz
    Jan 4, 2011 at 2:53
  • +1, Actually, I got the same output with the one caveat, diff -rq reported a linked file as 'No such file or directory'. So, plus one for correct, and frankly simpler usage. (even if IVA's answer is a better 'learning opportunity' for process substitution (>_<)
    – xtian
    Oct 18, 2013 at 0:40
  • 1
    This is much slower than diffing the file names: the entirety of every file has to be read and compared.
    – Zaz
    Sep 30, 2014 at 20:39
  • @Josh of course, because it does recursively....
    – Braiam
    Oct 6, 2014 at 19:37
  • 1
    @Braiam: Even if you recursively diff the file names (using rsync with the --dry-run option, for example), it would still be much faster than diff -r.
    – Zaz
    Oct 11, 2014 at 12:36
0

Neither answers did the work for me as :

  1. I needed the diff to be recursive
  2. My folders were not side by side

Inspired from @Ignacio Vazquez-Abrams I used :

diff <(find PATH1 | sed 's"PATH1""') <(find PATH2 | sed 's"PATH2""')

Which does the job just fine and can be adapted for a nifty script :

#!/bin/bash
# Usage : compDirs dir1 dir2
# compare the file/folder names recursively in Dir1 and Dir2
 
PATH1=$1 
PATH2=$2

diff <(find $PATH1 | sed "s#$PATH1##") <(find $PATH2 | sed "s#$PATH2##")
1
  • A variant without sed would be diff <(cd $PATH1 && find .) <(cd $PATH2 && find .). As these are subprocesses the cd won't propagate to parent processes.
    – VRehnberg
    Dec 20, 2022 at 9:44
0

Expanding on this, since I don't have enough points to comment, the options -y (to show in two columns) and --suppress-common-lines make it even better!

diff -y --suppress-common-lines <(ls -1a ./dir1) <(ls -1a ./dir2)

You can remove -a from ls parts if not interested in dot/hidden files.

You must log in to answer this question.

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