Come confrontare file con gli stessi nomi in due directory diverse usando uno script di shell

StackOverflow https://stackoverflow.com/questions/119788

  •  02-07-2019
  •  | 
  •  

Domanda

Prima di passare a utilizzare SVN, gestivo il mio progetto semplicemente mantenendo una directory / develop / e modificando e testando i file lì, quindi spostandoli nella / main / directory. Quando ho deciso di passare a SVN, dovevo essere sicuro che le directory fossero effettivamente sincronizzate.

Quindi, qual è un buon modo per scrivere uno script di shell [bash] per confrontare ricorsivamente file con lo stesso nome in due directory diverse?

Nota: i nomi di directory utilizzati sopra sono solo per esempio. Non consiglio di archiviare il codice al livello più alto :).

È stato utile?

Soluzione

Il comando diff ha un'opzione -r per confrontare ricorsivamente le directory:

diff -r /develop /main

Altri suggerimenti

diff -rqu /develop /main

Ti fornirà solo un riepilogo delle modifiche in questo modo :)

Se vuoi vedere solo file nuovi / mancanti

diff -rqu /develop /main | grep "^Only

Se vuoi metterli a nudo:

diff -rqu /develop /main | sed -rn "/^Only/s/^Only in (.+?): /\1/p"

La diff che ho a disposizione consente differenze ricorsive:

diff -r main develop

Ma con uno script di shell:

( cd main ; find . -type f -exec diff {} ../develop/{} ';' )

[Ho letto da qualche parte che rispondere alle tue domande è OK, quindi ecco :)]

Ci ho provato e ha funzionato abbastanza bene

[/]$ cd /develop/
[/develop/]$ find | while read line; do diff -ruN "/main/$line" $line; done |less

Puoi scegliere di confrontare solo file specifici [ad esempio, solo quelli .php] modificando la riga sopra come

[/]$ cd /develop/
[/develop/]$ find -name "*.php" | while read line; do diff -ruN "/main/$line" $line; done |less

Altre idee?

ecco un esempio di un mio script (piuttosto disordinato), dircompare.sh , che:

  • ordina i file e le directory negli array a seconda della directory in cui si trovano (o entrambi), in due passaggi ricorsivi
  • I file presenti in entrambe le directory, vengono nuovamente ordinati in due array, a seconda che diff -q determini se differiscono o meno
  • per quei file che diff sono uguali, mostra e confronta i timestamp

Spero che possa essere trovato utile - Saluti!

EDIT2: ( In realtà, funziona bene con i file remoti - il problema è stato il segnale Ctrl-C non gestito durante un'operazione diff tra file locale e remoto, che può richiedere del tempo; script ora aggiornato con una trap da gestire che - tuttavia, lasciando la modifica precedente di seguito come riferimento ):

EDIT: ... tranne che sembra mandare in crash il mio server per una directory ssh remota (che ho provato ad usare su ~ / .gvfs ) ... Quindi questo non è bash più, ma suppongo che un'alternativa sia usare rsync , ecco un esempio:

$ # get example revision 4527 as testdir1
$ svn co https://openbabel.svn.sf.net/svnroot/openbabel/openbabel/trunk/data@4527 testdir1

$ # get earlier example revision 2729 as testdir2
$ svn co https://openbabel.svn.sf.net/svnroot/openbabel/openbabel/trunk/data@2729 testdir2

$ # use rsync to generate a list 
$ rsync -ivr --times --cvs-exclude --dry-run testdir1/ testdir2/
sending incremental file list
.d..t...... ./
>f.st...... CMakeLists.txt
>f.st...... MACCS.txt
>f..t...... SMARTS_InteLigand.txt
...
>f.st...... atomtyp.txt
>f+++++++++ babel_povray3.inc
>f.st...... bin2hex.pl
>f.st...... bondtyp.h
>f..t...... bondtyp.txt
...

Nota che:

  • Per ottenere quanto sopra, non devi dimenticare le barre finali / alla fine dei nomi delle directory in rsync
  • --dry-run - simula solo, non aggiornare / trasferire file
  • -r - ricorre nelle directory
  • -v - dettagliato (ma non relativo alle informazioni sulle modifiche ai file)
  • --cvs-exclude - ignora i file .svn
  • -i - " - itemize-changes: genera un riepilogo delle modifiche per tutti gli aggiornamenti "

Ecco un breve estratto di man rsync che spiega le informazioni mostrate da -i (ad esempio, > f.st .... .. sopra):

The  "%i"  escape  has a cryptic output that is 11 letters long.
The general format is like the string YXcstpoguax,  where  Y  is
replaced  by the type of update being done, X is replaced by the
file-type, and the other letters represent attributes  that  may
be output if they are being modified.

The update types that replace the Y are as follows:

o      A  < means that a file is being transferred to the remote
       host (sent).

o      A > means that a file is being transferred to  the  local
       host (received).

o      A  c  means that a local change/creation is occurring for
       the item (such as the creation  of  a  directory  or  the
       changing of a symlink, etc.).

...
The file-types that replace the X are: f for a file, a d  for  a
directory,  an  L for a symlink, a D for a device, and a S for a
special file (e.g. named sockets and fifos).

The other letters in the string above  are  the  actual  letters
that  will be output if the associated attribute for the item is
being updated or a "." for no change.  Three exceptions to  this
are:  (1)  a newly created item replaces each letter with a "+",
(2) an identical item replaces the dots with spaces, and (3)  an
....

Un po 'enigmatico, anzi - ma almeno mostra un confronto di directory di base su ssh . Cheers!

La risposta classica (System V Unix) sarebbe dircmp dir1 dir2 , che era uno script di shell che elencava i file trovati in dir1 ma non in dir2 o in dir2 ma non in dir1 all'inizio ( prima pagina di output, dal comando pr , quindi impaginato con le intestazioni), seguito da un confronto di ogni file comune con un'analisi (stessa directory diversa erano i risultati più comuni).

Questo sembra essere in procinto di svanire - ne ho una reimplementazione indipendente disponibile se ne hai bisogno. Non è scienza missilistica ( cmp è tuo amico).

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top