diff to output only the file names

LinuxCommand LineDiff

Linux Problem Overview


I'm looking to run a Linux command that will recursively compare two directories and output only the file names of what is different. This includes anything that is present in one directory and not the other or vice versa, and text differences.

Linux Solutions


Solution 1 - Linux

From the diff man page:

> -q   Report only whether the files differ, not the details of the differences.
> -r   When comparing directories, recursively compare any subdirectories found.

Example command:

diff -qr dir1 dir2

Example output (depends on locale):

$ ls dir1 dir2
dir1:
same-file  different  only-1

dir2:
same-file  different  only-2
$ diff -qr dir1 dir2
Files dir1/different and dir2/different differ
Only in dir1: only-1
Only in dir2: only-2

Solution 2 - Linux

You can also use rsync

rsync -rv --size-only --dry-run /my/source/ /my/dest/ > diff.out

Solution 3 - Linux

If you want to get a list of files that are only in one directory and not their sub directories and only their file names:

diff -q /dir1 /dir2 | grep /dir1 | grep -E "^Only in*" | sed -n 's/[^:]*: //p'

If you want to recursively list all the files and directories that are different with their full paths:

diff -rq /dir1 /dir2 | grep -E "^Only in /dir1*" | sed -n 's/://p' | awk '{print $3"/"$4}'

This way you can apply different commands to all the files.

For example I could remove all the files and directories that are in dir1 but not dir2:

diff -rq /dir1 /dir2 | grep -E "^Only in /dir1*" | sed -n 's/://p' | awk '{print $3"/"$4}' xargs -I {} rm -r {}

Solution 4 - Linux

The approach of running diff -qr old/ new/ has one major drawback: it may miss files in newly created directories. E.g. in the example below the file data/pages/playground/playground.txt is not in the output of diff -qr old/ new/ whereas the directory data/pages/playground/ is (search for playground.txt in your browser to quickly compare). I also posted the following solution on Unix & Linux Stack Exchange, but I'll copy it here as well:

To create a list of new or modified files programmatically the best solution I could come up with is using rsync, sort, and uniq:

(rsync -rcn --out-format="%n" old/ new/ && rsync -rcn --out-format="%n" new/ old/) | sort | uniq

Let me explain with this example: we want to compare two dokuwiki releases to see which files were changed and which ones were newly created.

We fetch the tars with wget and extract them into the directories old/ and new/:

wget http://download.dokuwiki.org/src/dokuwiki/dokuwiki-2014-09-29d.tgz
wget http://download.dokuwiki.org/src/dokuwiki/dokuwiki-2014-09-29.tgz
mkdir old && tar xzf dokuwiki-2014-09-29.tgz -C old --strip-components=1
mkdir new && tar xzf dokuwiki-2014-09-29d.tgz -C new --strip-components=1

Running rsync one way might miss newly created files as the comparison of rsync and diff shows here:

rsync -rcn --out-format="%n" old/ new/

yields the following output:

VERSION
doku.php
conf/mime.conf
inc/auth.php
inc/lang/no/lang.php
lib/plugins/acl/remote.php
lib/plugins/authplain/auth.php
lib/plugins/usermanager/admin.php

Running rsync only in one direction misses the newly created files and the other way round would miss deleted files, compare the output of diff:

diff -qr old/ new/

yields the following output:

Files old/VERSION and new/VERSION differ
Files old/conf/mime.conf and new/conf/mime.conf differ
Only in new/data/pages: playground
Files old/doku.php and new/doku.php differ
Files old/inc/auth.php and new/inc/auth.php differ
Files old/inc/lang/no/lang.php and new/inc/lang/no/lang.php differ
Files old/lib/plugins/acl/remote.php and new/lib/plugins/acl/remote.php differ
Files old/lib/plugins/authplain/auth.php and new/lib/plugins/authplain/auth.php differ
Files old/lib/plugins/usermanager/admin.php and new/lib/plugins/usermanager/admin.php differ

Running rsync both ways and sorting the output to remove duplicates reveals that the directory data/pages/playground/ and the file data/pages/playground/playground.txt were missed initially:

(rsync -rcn --out-format="%n" old/ new/ && rsync -rcn --out-format="%n" new/ old/) | sort | uniq

yields the following output:

VERSION
conf/mime.conf
data/pages/playground/
data/pages/playground/playground.txt
doku.php
inc/auth.php
inc/lang/no/lang.php
lib/plugins/acl/remote.php
lib/plugins/authplain/auth.php
lib/plugins/usermanager/admin.php

rsync is run with theses arguments:

  • -r to "recurse into directories",
  • -c to also compare files of identical size and only "skip based on checksum, not mod-time & size",
  • -n to "perform a trial run with no changes made", and
  • --out-format="%n" to "output updates using the specified FORMAT", which is "%n" here for the file name only

The output (list of files) of rsync in both directions is combined and sorted using sort, and this sorted list is then condensed by removing all duplicates with uniq

Solution 5 - Linux

On my linux system to get just the filenames

diff -q /dir1 /dir2|cut -f2 -d' '

Solution 6 - Linux

I have a directory.

$ tree dir1
dir1
├── a
│   └── 1.txt
├── b
│   └── 2.txt
└── c
    ├── 3.txt
    ├── 4.txt
    └── d
        └── 5.txt

4 directories, 5 files

I have another directory.

$ tree dir2
dir2
├── a
│   └── 1.txt
├── b
└── c
    ├── 3.txt
    ├── 5.txt
    └── d
        └── 5.txt

4 directories, 4 files

I can diff two directories.

$ diff <(cd dir1; find . -type f | sort) <(cd dir2; find . -type f| sort)
--- /dev/fd/11  2022-01-21 20:27:15.000000000 +0900
+++ /dev/fd/12  2022-01-21 20:27:15.000000000 +0900
@@ -1,5 +1,4 @@
 ./a/1.txt
-./b/2.txt
 ./c/3.txt
-./c/4.txt
+./c/5.txt
 ./c/d/5.txt

Solution 7 - Linux

rsync -rvc --delete --size-only --dry-run source dir target dir

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionbarfoonView Question on Stackoverflow
Solution 1 - LinuxJohn KugelmanView Answer on Stackoverflow
Solution 2 - LinuxboksioraView Answer on Stackoverflow
Solution 3 - LinuxN DView Answer on Stackoverflow
Solution 4 - LinuxiolsmitView Answer on Stackoverflow
Solution 5 - LinuxgerardwView Answer on Stackoverflow
Solution 6 - LinuxgenzouwView Answer on Stackoverflow
Solution 7 - LinuxmayankView Answer on Stackoverflow