Newsgroup: it.comp.os.linux.iniziare
Titolo: Confrontare due directory in bash

Salve a tutti.
Avrei bisogno di confrontare due directory e tutte le sottodirectory al 
loro interno, per sapere se i file contenuti corrispondono, e dovrei 
farlo da linea di comando per mettere il comando in cron.
La modalità di confronto directory di diff mi sembra eccessiva, perché 
tende a confrontare anche il contenuto dei file (almeno di quelli di 
testo), e su 150 GB di roba mi pare uno spreco di risorse... A me 
basterebbe confrontare nome, data e dimensione di ogni file.
Ho pensato anche a un ls -lR | sort, ma ls non mette il path completo 
davanti ai nomi dei file, quindi il risultato sarebbe un po' ambiguo, 
anche perché molte di queste directory hanno all'interno file con lo 
stesso nome.
Qualche idea? Proprio non esiste un comando apposito, a parte diff?
Grazie.
-- 
Ciao,
   Marco.

 Qualche idea? Proprio non esiste un comando apposito, a parte diff?
cosě puo' andare?
du dir1 > file1
du dir2 > file2
diff file1 file2 

 diff file1 file2 
Grazie, non avevo pensato a du.
Ci devo lavorare un po' ma credo sia una buona idea.
Innanzitutto devo usare -a per includere tutti i file nell'output, non 
solo le dir; poi miracolosamente ha anche l'opzione --time che aggiunge 
la data di modifica.
Ora devo capire perché su alcuni elementi vengono comunque delle 
differenze, credo nella dimensione, anche usando l'opzione -b...
...e poi lavorarci un po' con grep e sed per limare alcune imperfezioni.
-- 
Ciao,
   Marco.

 differenze, credo nella dimensione, anche usando l'opzione -b...
mah, mi pare strano, cioè du su due file *identici* da risultati diversi?

 Grazie.
Se usi il diff in modalità binaria va molto più veloce

 Grazie.
Puoi provare con rsync , che in genere e' piuttosto veloce per queste cose,
qualcosa tipo :
rsync -nrv /directory/uno/ /directory/due
occhio allo slash finale nella prima e a quello mancante nella seconda,
entrambi significativi. man rsync per i dettagli.
-- 
Ciao.
Alessandro 
"Ubuntu" - an African word, meaning "Slackware is too hard for me".

Grazie, non avevo pensato a du.
Ti basterebbe che sia diversa solo la data o no?
-- 
Saluti, Dalet

 qualcosa tipo :
Grazie, ma in realtà volevo usare qualcosa di diverso da rsync perché lo 
scopo della cosa è verificare un backup effettuato proprio con rsync ;).
-- 
Ciao,
   Marco.

 Ti basterebbe che sia diversa solo la data o no?
Hm, forse potrebbe bastare, dato che se i due file sono stati modificati 
nello stesso secondo è difficile che abbiano dimensioni diverse...
Cosa avevi in mente?
-- 
Ciao,
   Marco.

 Se usi il diff in modalità binaria va molto più veloce
Sarebbe la modalità predefinita, giusto? Perché nel man vedo solo 
l'opzione -a per forzarlo a considerare tutti i file come testo...
Dovrò provare effettivamente quanto tempo ci mette.
-- 
Ciao,
   Marco.

 mah, mi pare strano, cioč du su due file *identici* da risultati diversi?
Devo ricontrollare, e al momento non posso. Comunque credo si trattasse 
di cartelle... tenendo conto che du, se non ho capito male, non mostra 
la dimensione "esatta" del file, ma piuttosto l'occupazione in blocchi 
sul disco (e -b sembra dia una stima approssimativa), qualche differenza 
potrebbe essere dovuta ai diversi dischi su cui si trovano i due alberi 
di directory.
-- 
Ciao,
   Marco.

Il 06-07-2007, Marco De Vitis dice:



Questo, che visto il tuo reply su rsync forse ti puo' ancora
interessare (io non ci pensavo a rsync e da me do' questo
comando ma senza yes no).
Se devi confrontare in /tizio/dir2 con /caio/dir1
$ yes no | cp -auv /tizio/dir2 /caio/ 2> tmp/pippo
in pippo hai l'elenco di tutti e soli i file che avrebbe
aggiornato, ed invece non ne tocca nessuno.
-- 
Saluti, Dalet

 aggiornato, ed invece non ne tocca nessuno.
Uhm... però gli sfugge il caso in cui la dir destinazione contenga file 
che sono asssenti nella dir sorgente. È vero che di solito il problema 
di un backup è verificare che non avvenga il contrario ;), ma se voglio 
davvero fare le cose per bene...
Comunque, per curiosità: ho fatto una piccola prova ma non sembra aver 
funzionato, mi ha effettivamente copiato i file dalla sorgente nella 
destinazione.
Non capisco, in quale modo la sfilza di "no" generati da "yes no" 
dovrebbe impedire a cp di fare la copia?
-- 
Ciao,
   Marco.

dovrebbe impedire a cp di fare la copia?
Credo che gliene arrivi solo uno per volta... ci vorrebbe un
esperto.
Ma se uso l'altro modo per la redirezione:
cp ........ <yes n
non mi riesce piu' di acchiappare lo sterror 2.
Cmq da me non ne copia neppure uno, che diamine.
Ci riprovo, vediamo.
ls -lR /tmp/origine
/tmp/origine:
totale 20
-rw-r--r-- 1 dalet users 1816 2007-07-07 04:15 510001
-rw-r--r-- 1 dalet users 1292 2007-07-07 04:15 510002
-rw-r--r-- 1 dalet users 2821 2007-07-07 04:15 510003
drwxr-xr-x 2 dalet users 4096 2007-07-07 04:27 aaa
-rw-r--r-- 1 dalet users   33 2007-07-07 04:15 pippo
/tmp/origine/aaa:
totale 8
-rw-r--r-- 1 dalet users 1816 2007-07-07 04:15 510001
-rw-r--r-- 1 dalet users   33 2007-07-07 04:15 pippo
ls -lR /tmp/destin
/tmp/destin:
totale 20
-rw-r--r-- 1 dalet users 1816 2007-05-05 16:41 510001
-rw-r--r-- 1 dalet users 1292 2007-05-05 16:45 510002
-rw-r--r-- 1 dalet users 2821 2007-07-07 04:24 510003
drwxr-xr-x 2 dalet users 4096 2007-07-07 04:27 aaa
-rw-r--r-- 1 dalet users   33 2007-07-07 04:23 pippo
/tmp/destin/aaa:
totale 8
-rw-r--r-- 1 dalet users 1816 2007-05-05 16:41 510001
-rw-r--r-- 1 dalet users   33 2007-07-07 04:26 pippo
yes n|cp -auv /tmp/origine/* /tmp/destin/ 2>/tmp/pluto
cat /tmp/pluto
/bin/cp: sovrascrivo `/tmp/destin/510001'? /bin/cp: sovrascrivo
`/tmp/destin/510002'? /bin/cp: sovrascrivo `/tmp/destin/aaa/510001'? 
Questa e' una sola riga, l'ho spezzata adesso io... anzi
guarda:
cat /tmp/pluto | sed s/"\/bin\/cp: sovrascrivo "//g | tr -d '`' \
| tr '?' '\n' | tr -d '\47'
/tmp/destin/510001
 /tmp/destin/510002
 /tmp/destin/aaa/510001
E non me li ha toccati:
ls -lR /tmp/destin
/tmp/destin/:
totale 20
-rw-r--r-- 1 dalet users 1816 2007-05-05 16:41 510001
-rw-r--r-- 1 dalet users 1292 2007-05-05 16:45 510002
-rw-r--r-- 1 dalet users 2821 2007-07-07 04:24 510003
drwxr-xr-x 2 dalet users 4096 2007-07-07 04:27 aaa
-rw-r--r-- 1 dalet users   33 2007-07-07 04:23 pippo
/tmp/destin/aaa:
totale 8
-rw-r--r-- 1 dalet users 1816 2007-05-05 16:41 510001
-rw-r--r-- 1 dalet users   33 2007-07-07 04:26 pippo
-- 
Saluti, Dalet

 `/tmp/destin/510002'? /bin/cp: sovrascrivo `/tmp/destin/aaa/510001'? 
Ah ecco, il "no" sarebbe la risposta alla richiesta di sovrascrittura. E 
in effetti cosě funziona anche da me, se sorgente e destinazione 
contengono lo stesso file con data diversa.
Ma io prima avevo provato copiando una dir piena in una dir vuota, e 
ovviamente era stato copiato tutto senza nessun avviso. Questo purtroppo 
non va bene, se nella destinazione manca un file io voglio che mi venga 
solo segnalato, non posso permettergli di modificare i contenuti delle 
due dir, altrimenti mi viene fuori un gran pasticcio per altri motivi.
-- 
Ciao,
   Marco.

 mah, mi pare strano, cioè du su due file *identici* da risultati diversi?
Ok, ho ricontrollato, e nei 60 GB su cui ho fatto il test alla fine 
questa stranezza si verifica solo su una directory, che con "du -abS 
--time" risulta avere dimensione leggermente diversa fra originale e 
copia, non so dire perché, dato che contengono gli stessi file. Tendo a 
pensare ad una differenza nei blocchi usati a causa dei diversi dischi, 
che probabilmente impedisce a du di calcolare la vera dimensione; 
oltretutto la dir contiene molti piccoli file.
Questo potrebbe essere piuttosto fastidioso :-/.
Nel frattempo ho anche fatto una prova con diff sugli stessi 60 GB, ci 
ha messo circa mezz'ora, che non è poi tantissimo... ma il problema 
principale è che mi ha riportato differenze fra svariati file binari che 
con du apparivano identici 8-| (e in effetti _dovrebbero_ essere identici).
Ho notato però che sono tutti file .xls, più tre file .pps. Quindi mi 
viene il sospetto che la colpa sia di qualche porcheria che fa Office 
dentro ai file quando li apre, anche senza salvarli e senza cambiarne la 
data di modifica (altrimenti rsync li avrebbe nuovamente sincronizzati).
Ne sapete niente?
Insomma finora il metodo migliore è du, che però non è proprio perfetto.
-- 
Ciao,
   Marco.

Rispondo con quoting selvaggio in questo mio thread di oltre un mese
fa per mostrare, in sintesi, la soluzione che alla fine ho adottato:
cd dir1
find ./ -type f -printf "%p  %s  %Td/%Tm/%TY\n" | sort >/tmp/dir1.txt
find ./ -type d -printf "%p  %Td/%Tm/%TY\n" | sort >>/tmp/dir1.txt
cd dir2
find ./ -type f -printf "%p  %s  %Td/%Tm/%TY\n" | sort >/tmp/dir2.txt
find ./ -type d -printf "%p  %Td/%Tm/%TY\n" | sort >>/tmp/dir2.txt
diff /tmp/dir1.txt /tmp/dir2.txt
Così posso confrontare nome, dimensione e data di tutti i file, e nome
e data di tutte le directory. Il metodo è piuttosto veloce e funziona
bene.
--
Ciao,
  Marco.


bene.
Be' ma perche' "piuttosto veloce"? dovrebbe essere la
massima velocita' assoluta: legge solo come fosse ls, no?
In ogni caso mi sembra un'ottima soluzione... e mi serve
pure a me:-)
Pensa che era anche uno dei controlli dei primi antivirus
di winbug: ricordo ancora quel mare di maledetti file .CPS
della PCTools.
-- 
Saluti, Dalet

 massima velocita' assoluta: legge solo come fosse ls, no?
Be', sě, č veloce, ma immagino che se esistesse un comando apposito per 
fare il diff che serviva a me in una passata sola, senza fare due 
passate diverse (file e dir) per ciascuna delle due dir da confrontare 
piů il successivo diff, sarebbe ancora piů veloce ;).
-- 
Ciao,
   Marco.

 ... fare il diff [...] in una passata sola...
diff <(tree -ifDugps "${dir1}") <(tree -ifDugps "${dir2}")

 | sort >>/tmp/dir1.txt
Molto piu` veloce:
find ./ \
    -type f -printf "%p  %s  %Td/%Tm/%TY\n" \
    -or \
    -type d -printf "%p  %Td/%Tm/%TY\n" | 
  sort >/tmp/dir1.txt
NON TESTATO

 diff <(tree -ifDugps "${dir1}") <(tree -ifDugps "${dir2}")
Interessante, ma purtroppo ha lo stesso problema di "du": dato che le 
mie due directory sono su dischi molto diversi, a volte succede che 
alcune sottodirectory, pur essendo identiche, con du e tree risultino di 
dimensioni diverse, e quindi l'affidabilità del diff va a farsi benedire.
È per questo che con find prendo separatamente gli elenchi di file e 
dir, evitando di stampare la dimensione per le dir che tanto non mi 
interessa, avendo già quella di tutti i file.
BTW, gli argomenti esatti per tree per avere un output analogo a quello 
di find che serve a me sarebbero stati "-ifDans".
-- 
Ciao,
   Marco.

   sort >/tmp/dir1.txt
Già, è vero, grazie. Ora ho cambiato in questo modo il mio script, se 
non altro perché è più "elegante" ;). Sul "molto più veloce" ho qualche 
dubbio: su 150GB di dati, la vecchia versione impiegava circa 25 
secondi, e la nuova circa 24; provato diverse volte consecutivamente in 
entrambi i casi. Boh.
-- 
Ciao,
   Marco.

 secondi, e la nuova circa 24...
A causa dei buffer di lettura.
Il primo find legge le directory direttamente 
dal disco ma i buffer di lettura non vengono 
scaricati immediatamente (anzi rimangono in 
memoria molto a lungo) cosi` il secondo find
legge i buffer dalla memoria ed e` molto piu` 
veloce perche` il disco non viene coinvolto. 

 A causa dei buffer di lettura.
Non mi quadra molto, perché io ho provato per più volte consecutivamente 
sia l'una che l'altra versione; il discorso della differenza a causa dei 
buffer può valere solo la prima volta, ma dalla seconda in poi 
gareggiano alla pari. Voglio dire: supponendo che nel vecchio script il 
primo find impiegasse 20 secondi e il secondo solo 5 a causa del buffer 
(sto ipersemplificando, dato che in realtà lo script è un po' più 
complesso), lanciando lo stesso script subito dopo una seconda volta 
dovrebbero impiegare 5 secondi entrambi i find, per un totale di 10. E 
il nuovo script, lanciato anch'esso subito dopo, dovrebbe impiegare 
qualcosa meno. Invece i risultati erano sempre gli stessi, 25 e 24.
Ma ora ho capito: la stragrande maggioranza del tempo va via a causa del 
sort! I tempi del find in sé e le relative differenze invece sono 
trascurabili.
Dimostrazione con i dati già in cache:
#>time find ./ -type f -printf "%p  %Td/%Tm/%TY\n" >/tmp/dir1.txt
real    0m1.559s
user    0m0.440s
sys     0m1.092s
#>time find ./ -type d -printf "%p  %Td/%Tm/%TY\n" >/tmp/dir1.txt
real    0m0.815s
user    0m0.256s
sys     0m0.524s
#>time find ./ -type f -printf "%p  %Td/%Tm/%TY\n" -o -type d -printf 
"%p  %Td/%Tm/%TY\n" >/tmp/dir1.txt
real    0m1.744s
user    0m0.624s
sys     0m1.120s
#>time find ./ -type f -printf "%p  %Td/%Tm/%TY\n" -o -type d -printf 
"%p  %Td/%Tm/%TY\n" | sort >/tmp/dir1.txt
real    0m11.552s
user    0m10.393s
sys     0m1.220s
-- 
Ciao,
   Marco.