berbeda dengan hanya output nama file

244

Saya mencari untuk menjalankan perintah Linux yang secara rekursif akan membandingkan dua direktori dan hanya menghasilkan nama file yang berbeda. Ini termasuk apa pun yang ada dalam satu direktori dan bukan yang lain atau sebaliknya, dan perbedaan teks.

barfoon
sumber

Jawaban:

375

Dari halaman manual diff:

-q   Laporkan hanya apakah file berbeda, bukan detail perbedaannya.
-r   Ketika membandingkan direktori, secara rekursif membandingkan subdirektori yang ditemukan.

Contoh perintah:

diff -qr dir1 dir2

Output contoh (tergantung pada lokal):

$ 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
John Kugelman
sumber
Terima kasih - diffhalaman manual di CentOS 7 menggambarkan -qsebagai "laporkan hanya ketika file berbeda", yang kurang jelas dari apa yang Anda tulis.
Chap
2
Ini membandingkan konten aktual dari file yang sering kali diinginkan oleh seseorang, namun, jawaban rsync memberikan opsi untuk hanya melihat nama dan ukuran file, dan bukan kontennya; itu kadang-kadang diinginkan.
steveb
Bekerja pada macOS juga.
Marius Soutier
Juga, dapat termasuk -x PATTERNdalam perintah untuk mengecualikan subdirektori tertentu. Sebagai contoh, diff -qr repo1 repo2 -x ".git" akan membandingkan dua direktori tetapi akan mengecualikan jalur file dengan ".git" di dalamnya.
ViFI
27

Anda juga dapat menggunakan rsync

rsync -rv --size-only --dry-run /my/source/ /my/dest/ > diff.out
boksiora
sumber
6
--size-onlyakan kehilangan file dengan ukuran yang identik tetapi konten yang berbeda, mis. old / version.txt "29a" new / version.txt "29b" . Gunakan sebaliknya: di rsync -ric --dry-run old/ new/mana argumen "-i" memungkinkan untuk mendapatkan daftar file secara langsung melaluirsync -ric --dry-run old/ new/ | cut -d" " -f 2
iolsmit
6
Ini bagus jika Anda hanya mencari file yang hilang (terutama di seluruh jaringan berbagi), karena tidak membandingkan konten. Ini membantu saya menemukan beberapa file yang gagal saat bermigrasi ke NAS baru.
OverZealous
4
Pastikan untuk menyertakan trailing slash untuk jalur yang ditentukan pada baris perintah rsync. Tanpa mereka, ini tidak akan berfungsi dengan benar, dan rsync kemungkinan hanya akan menyebutkan semua nama file!
Vladimir Panteleev
2
Berkenaan dengan komentar tentang tidak memeriksa konten. Ini kadang-kadang diinginkan, setidaknya sebagai umpan pertama.
steveb
13

Jika Anda ingin mendapatkan daftar file yang hanya dalam satu direktori dan bukan sub direktori dan hanya nama file mereka:

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

Jika Anda ingin membuat daftar semua file dan direktori yang berbeda dengan path lengkapnya secara rekursif:

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

Dengan cara ini Anda dapat menerapkan perintah berbeda untuk semua file.

Misalnya saya bisa menghapus semua file dan direktori yang ada di dir1 tetapi tidak dir2:

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

Di sistem linux saya hanya mendapatkan nama file

diff -q /dir1 /dir2|cut -f2 -d' '
gerardw
sumber
7
Saya tidak menaruh nama file dengan spasi di sistem linux saya. ;)
gerardw
6
Saya tidak bermaksud menyalahkan ini untuk Anda ... ;-p Seperti petunjuk bagi seseorang yang ...
michuelnik
tidak bekerja untuk saya. Struktur direktori saya seperti di bawah iniaudit-0.0.234/audit-data-warehouse-0.0.234/ audit-0.0.235/audit-data-warehouse-0.0.235/
Alex Raj Kaliamoorthy
diff -qrN /dir1 /dir2 | cut -f2 -d' 'bekerja dengan baik untuk saya!
Francesco
9

Pendekatan menjalankan diff -qr old/ new/memiliki satu kelemahan utama: mungkin kehilangan file di direktori yang baru dibuat. Misalnya dalam contoh di bawah file data/pages/playground/playground.txttidak dalam output diff -qr old/ new/sedangkan direktori data/pages/playground/(cari playground.txt di browser Anda untuk dengan cepat membandingkan). Saya juga memposting solusi berikut di Unix & Linux Stack Exchange , tetapi saya juga akan menyalinnya di sini:

Untuk membuat daftar file baru atau yang dimodifikasi secara terprogram, solusi terbaik yang dapat saya gunakan adalah menggunakan rsync , sortir , dan uniq :

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

Izinkan saya menjelaskan dengan contoh ini: kami ingin membandingkan dua rilis dokuwiki untuk melihat file mana yang diubah dan mana yang baru dibuat.

Kami mengambil ter dengan wget dan mengekstraknya ke direktori old/dan 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

Menjalankan rsync salah satu cara mungkin kehilangan file yang baru dibuat karena perbandingan rsync dan diff ditampilkan di sini:

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

menghasilkan output berikut:

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

Menjalankan rsync hanya dalam satu arah melewatkan file yang baru dibuat dan sebaliknya akan kehilangan file yang dihapus, bandingkan output dari diff:

diff -qr old/ new/

menghasilkan output berikut:

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

Menjalankan rsync baik cara dan menyortir output untuk menghapus duplikat menunjukkan bahwa direktori data/pages/playground/dan filedata/pages/playground/playground.txt pada awalnya tidak terjawab:

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

menghasilkan output berikut:

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 Dijalankan dengan argumen tesis:

  • -r untuk "berulang ke direktori",
  • -c untuk juga membandingkan file dengan ukuran identik dan hanya "lewati berdasarkan checksum, bukan mod-time & size",
  • -n untuk "melakukan uji coba tanpa perubahan yang dibuat", dan
  • --out-format="%n" ke "keluaran pembaruan menggunakan FORMAT yang ditentukan", yaitu "% n" di sini hanya untuk nama file

Output (daftar file) dari rsynckedua arah digabungkan dan diurutkan menggunakan sort, dan daftar yang diurutkan ini kemudian diringkas dengan menghapus semua duplikat denganuniq

iolsmit
sumber
Tidak bisakah Anda menjalankannya mundur ( diff new/ old/) untuk melihat direktori mana yang dihapus?
Jacques
Berjalan diff -qr new/ old/pada contoh di atas dengan tars dokuwiki menghasilkan output yang sama dengan diff -qr old/ new/- yaitu Anda melihat bahwa direktori baru / hilang tetapi bukan file di dalamnya
iolsmit
-4
rsync -rvc --delete --size-only --dry-run source dir target dir
mayank
sumber