it-swarm.it

Differenza tra due directory in Linux

Sto cercando di trovare i file esistenti in una directory ma non nell'altra, ho provato a usare questo comando:

diff -q dir1 dir2

Il problema con il comando precedente che trova entrambi i file in dir1 ma non in dir2 così come i file in dir2 ma non in dir1

Sto cercando di trovare i file in dir1 ma non solo in dir2.

Ecco un piccolo esempio di come sono i miei dati

dir1    dir2    dir3
1.txt   1.txt   1.txt
2.txt   3.txt   3.txt
5.txt   4.txt   5.txt
6.txt   7.txt   8.txt

Un'altra domanda sulla mia mente è come posso trovare i file in dir1 ma non in dir2 o dir3 in un singolo comando?

242
Error404
diff -r dir1 dir2 | grep dir1 | awk '{print $4}' > difference1.txt

Spiegazione:

  • diff -r dir1 dir2 mostra quali file sono solo in dir1 e quelli solo in dir2 e anche i cambiamenti dei file presenti in entrambe le directory, se presenti.

  • diff -r dir1 dir2 | grep dir1 mostra quali file sono solo in dir1

  • awk per stampare solo il nome del file.

343
asclepix

Questo dovrebbe fare il lavoro:

diff -rq dir1 dir2

Opzioni spiegate (tramite diff (1) man page ):

  • -r - Confronta in modo ricorsivo qualsiasi sottodirectory trovata.
  • -q - Emette solo se i file differiscono.
102
tokhi
comm -23 <(ls dir1 |sort) <(ls dir2|sort)

Questo comando ti darà i file che sono in dir1 e not in dir2.

A proposito di <( ) sign, puoi google it come "process replace".

45
plhn

Un buon modo per fare questo confronto è usare find con md5sum, quindi un diff.

Esempio:

Utilizzare find per elencare tutti i file nella directory, quindi calcolare l'hash md5 per ogni file e collegarlo a un file:

find /dir1/ -type f -exec md5sum {} \; > dir1.txt

Esegui la stessa procedura per un'altra directory:

find /dir2/ -type f -exec md5sum {} \; > dir2.txt

Quindi confronta i risultati con due file con "diff":

diff dir1.txt dir2.txt

Questa strategia è molto utile quando le due directory da confrontare non sono nella stessa macchina ed è necessario assicurarsi che i file siano uguali in entrambe le directory.

Un altro buon modo per fare il lavoro è usare git

git diff --no-index dir1/ dir2/

I migliori saluti!

27
Adail Junior

Meld ( http://meldmerge.org/ ) fa un ottimo lavoro nel confrontare directory e file all'interno.

 Meld comparing directories

13
Catalin Hritcu

vim's DirDiff plugin è un altro strumento molto utile per confrontare le directory.

vim -c "DirDiff dir1 dir2"

Non solo elenca quali file sono diversi tra le directory, ma consente anche di ispezionare/modificare con vimdiff i file che sono diversi.

10
drrossum

Insoddisfatto di tutte le risposte, poiché la maggior parte di esse funziona molto lentamente e genera un output inutilmente lungo per le directory di grandi dimensioni, ho scritto il mio script Python per confrontare due cartelle.

A differenza di molte altre soluzioni, non confronta il contenuto dei file. Inoltre non entra nelle sottodirectory che mancano in un'altra directory. Quindi l'output è abbastanza conciso e lo script funziona velocemente.

#!/usr/bin/env python3

import os, sys

def compare_dirs(d1: "old directory name", d2: "new directory name"):
    def print_local(a, msg):
        print('DIR ' if a[2] else 'FILE', a[1], msg)
    # ensure validity
    for d in [d1,d2]:
        if not os.path.isdir(d):
            raise ValueError("not a directory: " + d)
    # get relative path
    l1 = [(x,os.path.join(d1,x)) for x in os.listdir(d1)]
    l2 = [(x,os.path.join(d2,x)) for x in os.listdir(d2)]
    # determine type: directory or file?
    l1 = sorted([(x,y,os.path.isdir(y)) for x,y in l1])
    l2 = sorted([(x,y,os.path.isdir(y)) for x,y in l2])
    i1 = i2 = 0
    common_dirs = []
    while i1<len(l1) and i2<len(l2):
        if l1[i1][0] == l2[i2][0]:      # same name
            if l1[i1][2] == l2[i2][2]:  # same type
                if l1[i1][2]:           # remember this folder for recursion
                    common_dirs.append((l1[i1][1], l2[i2][1]))
            else:
                print_local(l1[i1],'type changed')
            i1 += 1
            i2 += 1
        Elif l1[i1][0]<l2[i2][0]:
            print_local(l1[i1],'removed')
            i1 += 1
        Elif l1[i1][0]>l2[i2][0]:
            print_local(l2[i2],'added')
            i2 += 1
    while i1<len(l1):
        print_local(l1[i1],'removed')
        i1 += 1
    while i2<len(l2):
        print_local(l2[i2],'added')
        i2 += 1
    # compare subfolders recursively
    for sd1,sd2 in common_dirs:
        compare_dirs(sd1, sd2)

if __name__=="__main__":
    compare_dirs(sys.argv[1], sys.argv[2])

Esempio di utilizzo:

[email protected]:~$ python3 compare_dirs.py dir1/ dir2/
DIR  dir1/out/flavor-domino removed
DIR  dir2/out/flavor-maxim2 added
DIR  dir1/target/vendor/flavor-domino removed
DIR  dir2/target/vendor/flavor-maxim2 added
FILE dir1/tmp/.kconfig-flavor_domino removed
FILE dir2/tmp/.kconfig-flavor_maxim2 added
DIR  dir2/tools/tools/LiveSuit_For_Linux64 added

O se vuoi vedere solo i file dalla prima directory: 

[email protected]:~$ python3 compare_dirs.py dir2/ dir1/ | grep dir1
DIR  dir1/out/flavor-domino added
DIR  dir1/target/vendor/flavor-domino added
FILE dir1/tmp/.kconfig-flavor_domino added

Post scriptum Se è necessario confrontare le dimensioni dei file e gli hash dei file per le potenziali modifiche, ho pubblicato uno script aggiornato qui: https://Gist.github.com/amakukha/f489cbde2afd32817f8e866cf4abe779

9
Andriy Makukha

Un altro approccio (forse più veloce per le grandi directory):

$ find dir1 | sed 's,^[^/]*/,,' | sort > dir1.txt && find dir2 | sed 's,^[^/]*/,,' | sort > dir2.txt
$ diff dir1.txt dir2.txt

Il comando sed rimuove il primo componente della directory grazie al post di Erik )

5
jaltek

Questo è un po 'tardi ma può aiutare qualcuno. Non sono sicuro se diff o rsync sputino solo nomi di file in un formato nuda come questo. Grazie a plhn per aver dato quella soluzione di Nizza che ho ampliato in seguito.

Se vuoi solo i nomi dei file quindi è facile copiare semplicemente i file che ti servono in un formato pulito, puoi usare il comando find.

comm -23 <(find dir1 | sed 's/dir1/\//'| sort) <(find dir2 | sed 's/dir2/\//'| sort) | sed 's/^\//dir1/'

Ciò presuppone che sia dir1 che dir2 si trovino nella stessa cartella principale. sed rimuove solo la cartella principale in modo da poter confrontare le mele con le mele. L'ultimo sed semplicemente riporta il nome di dir1.

Se vuoi solo i file:

comm -23 <(find dir1 -type f | sed 's/dir1/\//'| sort) <(find dir2 -type f | sed 's/dir2/\//'| sort) | sed 's/^\//dir1/'

Allo stesso modo per le directory:

comm -23 <(find dir1 -type d | sed 's/dir1/\//'| sort) <(find dir2 -type d | sed 's/dir2/\//'| sort) | sed 's/^\//dir1/'
4
James

La risposta accettata elencherà anche i file presenti in entrambe le directory, ma con contenuti diversi. Per elencare SOLO i file esistenti in dir1 puoi utilizzare:

diff -r dir1 dir2 | grep 'Only in' | grep dir1 | awk '{print $4}' > difference1.txt

Spiegazione: 

  • diff -r dir1 dir2: confronta
  • grep 'Only in': ottieni le linee che contengono 'Only in'
  • grep dir1: ottiene le linee che contengono dir
4
Aris

Questo è lo script di bash per stampare comandi per sincronizzare due directory

dir1=/tmp/path_to_dir1
dir2=/tmp/path_to_dir2
diff -rq $dir1 $dir2 | sed -e "s|Only in $dir2\(.*\): \(.*\)|cp -r $dir2\1/\2 $dir1\1|" |  sed -e "s|Only in $dir1\(.*\): \(.*\)|cp -r $dir1\1/\2 $dir2\1|" 
1
Ebru Yener

Questa risposta ottimizza uno dei suggerimenti di @ Adail-Junior aggiungendo l'opzione -D, che è utile quando nessuna delle directory che vengono confrontate è git repository:

git diff -D --no-index dir1/ dir2/

Se usi -D allora non vedrai confronti con /dev/null: text Binary files a/whatever and /dev/null differ

1
Mike Slinn

GNU grep può inversione della ricerca con l'opzione -v. Ciò rende grep che riporta le righe, che non corrispondono. Con questo puoi rimuovere i file in dir2 dall'elenco di file in dir1.

grep -v -F -x -f <(find dir2 -type f -printf '%P\n') <(find dir1 -type f -printf '%P\n')

Le opzioni -F -x dicono grep per eseguire una ricerca di stringa sull'intera riga.

0
ceving

Un modo semplificato per confrontare 2 directory usando il comando DIFF

diff filename.1 filename.2> filename.dat >> Invio

aprire filename.dat al termine dell'esecuzione

e vedrai: Solo in filename.1: filename.2 Solo in: directory_name: name_of_file1 Solo in: directory_Name: nome_file2

0
nerakk

kdiff3 ha un'interfaccia diff piacevole per file e directory.

Funziona su Windows, Linux e macOS.

Puoi installarlo in diversi modi:

0
ayakout