diff per generare solo i nomi dei file


244

Sto cercando di eseguire un comando Linux che confronterà ricorsivamente due directory e produrrà solo i nomi dei file di ciò che è diverso. Ciò include tutto ciò che è presente in una directory e non nell'altra o viceversa, e differenze di testo.

Risposte:


376

Dalla pagina man diff:

-q   Segnala solo se i file differiscono, non i dettagli delle differenze.
-r   Quando si confrontano le directory, confrontare ricorsivamente tutte le sottodirectory trovate.

Esempio di comando:

diff -qr dir1 dir2

Esempio di output (dipende dalle impostazioni locali):

$ 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

Grazie - la diffpagina man di CentOS 7 descrive -qcome "segnala solo quando i file differiscono", il che è meno chiaro di quello che hai scritto.
Cap

2
Questo confronta il contenuto effettivo dei file che è spesso ciò che si desidera, tuttavia, la risposta rsync offre la possibilità di guardare solo i nomi e le dimensioni dei file, e non il contenuto; a volte è desiderabile.
steveb,

Funziona anche su macOS.
Marius Soutier,

Inoltre, può includere -x PATTERNnel comando per escludere determinate sottodirectory. Ad esempio, diff -qr repo1 repo2 -x ".git" confronteranno due directory ma escluderanno i percorsi dei file con ".git" in esse.
ViFI,

27

Puoi anche usare rsync

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

6
--size-onlymancheranno file di dimensioni identiche ma con contenuti diversi, ad es. old / version.txt "29a" new / version.txt "29b" . Utilizzare invece: rsync -ric --dry-run old/ new/dove l'argomento "-i" consente di ottenere l'elenco dei file direttamente tramitersync -ric --dry-run old/ new/ | cut -d" " -f 2
iolsmit

6
Questo è ottimo se stai cercando solo file mancanti (specialmente tra le condivisioni di rete), perché non confronta i contenuti. Questo mi ha aiutato a trovare alcuni file non riusciti durante la migrazione a un nuovo NAS.
OverZealous

4
Assicurati di includere la barra finale per i percorsi specificati nella riga di comando di rsync. Senza di loro, questo non funzionerà correttamente e probabilmente rsync enumererà tutti i nomi dei file!
Vladimir Panteleev,

2
Per quanto riguarda i commenti su non controllare il contenuto. Questo è talvolta desiderabile, almeno come primo passaggio.
steveb,

13

Se si desidera ottenere un elenco di file che si trovano solo in una directory e non nelle relative sottodirectory e solo nei nomi dei file:

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

Se si desidera elencare in modo ricorsivo tutti i file e le directory che sono diversi con i loro percorsi completi:

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

In questo modo è possibile applicare diversi comandi a tutti i file.

Ad esempio, potrei rimuovere tutti i file e le directory che si trovano in dir1 ma non in dir2:

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

9

Sul mio sistema Linux per ottenere solo i nomi dei file

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

7
Non inserisco nomi di file con spazi sul mio sistema Linux. ;)
gerardw,

6
Non intendevo imputarti questo ... ;-p Solo un suggerimento per qualcuno che lo fa ...
Michuelnik,

Non funziona per me. La mia struttura di directory è come sottoaudit-0.0.234/audit-data-warehouse-0.0.234/ audit-0.0.235/audit-data-warehouse-0.0.235/
Alex Raj Kaliamoorthy il

diff -qrN /dir1 /dir2 | cut -f2 -d' 'funziona bene per me!
Francesco,

9

L'approccio della corsa diff -qr old/ new/ha un grosso svantaggio: potrebbe mancare i file nelle directory appena create. Ad esempio nell'esempio di seguito il file data/pages/playground/playground.txtnon è nell'output di diff -qr old/ new/mentre la directory data/pages/playground/è (cerca playground.txt nel tuo browser per confrontare rapidamente). Ho anche pubblicato la seguente soluzione su Unix & Linux Stack Exchange , ma la copierò anche qui:

Per creare un elenco di file nuovi o modificati a livello di codice, la soluzione migliore che ho potuto trovare è usare rsync , sort e uniq :

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

Lasciatemi spiegare con questo esempio: vogliamo confrontare due versioni di dokuwiki per vedere quali file sono stati modificati e quali sono stati appena creati.

Prendiamo i tars con wget e li estraiamo nelle directory old/e 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

L'esecuzione di rsync in un modo potrebbe perdere i file appena creati come il confronto tra rsync e diff mostra qui:

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

produce il seguente 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

Eseguendo rsync solo in una direzione mancano i file appena creati e viceversa mancherebbero i file eliminati, confrontare l'output di diff:

diff -qr old/ new/

produce il seguente 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

L'esecuzione di rsync in entrambi i modi e l'ordinamento dell'output per rimuovere i duplicati rivela che inizialmente la directory data/pages/playground/e il file non data/pages/playground/playground.txtsono stati rilevati:

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

produce il seguente 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 viene eseguito con questi argomenti:

  • -r "ricorrere alle directory",
  • -c per confrontare anche file di dimensioni identiche e solo "salta in base al checksum, non a mod-time e dimensioni",
  • -n per "eseguire una corsa di prova senza apportare modifiche" e
  • --out-format="%n" a "output aggiornamenti usando il FORMATO specificato", che è "% n" qui solo per il nome del file

L'output (elenco di file) rsyncin entrambe le direzioni viene combinato e ordinato utilizzando sort, e questo elenco ordinato viene quindi condensato rimuovendo tutti i duplicati conuniq


Non potresti semplicemente eseguirlo all'indietro ( diff new/ old/) per vedere quali directory sono state eliminate?
Jacques,

L'esecuzione diff -qr new/ old/dell'esempio sopra con i dokuwiki tars produce lo stesso output di diff -qr old/ new/- cioè vedi che la directory è nuova / mancante ma non i file in essa contenuti
iolsmit

-4
rsync -rvc --delete --size-only --dry-run source dir target dir
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.