beda hanya untuk jenis file tertentu

12

Apakah ada cara saya dapat melakukan diff dua direktori secara rekursif tetapi hanya membandingkan (di tempat masing-masing) file yang cocok dengan nama file tertentu atau predikat tipe file?

Misalnya saya ingin melakukan sesuatu seperti

diff -r dir-a dir-b -filenames *.java, ivy.xml, build.xml

... atau bahkan lebih baik:

diff -r dir-a dir-b -filetype text

Jelas itu tidak wajib untuk digunakan diffkarena saya kira mantera finddan -exec diffmungkin juga melakukan trik (saya hanya tidak tahu bagaimana menghasilkan filepath komplementer dalam kasus terakhir).

Marcus Junius Brutus
sumber
3
Ada opsi untuk mengecualikan file yang cocok dengan pola, saya tidak melihat opsi untuk memasukkan hanya file yang cocok dengan pola.
Barmar
1
Semua opsi khusus untuk membandingkan direktori dapat ditemukan di gnu.org/software/diffutils/manual/html_node/…
Barmar
1
lihat tautan ini dan lihat jawaban Sérgio.
yehudah
1
stackoverflow.com/q/10131908/2707864
sancho.s ReinstateMonicaCellio

Jawaban:

1

Shellscript differ-r

Shellscript ini dapat melakukan diff dua direktori secara rekursif tetapi hanya membandingkan (di tempat masing-masing) file yang cocok dengan nama file atau pola tipe file tertentu.

#!/bin/bash

greenvid="\0033[32m"
resetvid="\0033[0m"

if [ $# -ne 3 ]
then
 echo "Usage: compare files in two directories including subdirectories"
 echo "         $0 <source-dir> <target-dir> <pattern>"
 echo "Example: $0  subdir-1     subdir-2     \"*.txt\""
 exit
fi

cmd='for pathname do
        greenvid="\0033[32m"
        resetvid="\0033[0m"
        echo -e "${greenvid}diff \"$pathname\" \"${pathname/'\"$1\"'/'\"$2\"'}\"${resetvid}"
        diff "$pathname" "${pathname/'\"$1\"'/'\"$2\"'}"
    done'
#echo "$cmd"

find "$1" -type f -name "$3" -exec bash -c "$cmd" bash {} +

Demo

File:

$ find -type f
./1/ett.txt
./1/two.doc
./1/t r e.txt
./1/sub/only-one.doc
./1/sub/hello.doc
./1/sub/hejsan.doc
./differ-r2
./differ-r1
./differ-r
./2/ett.txt
./2/two.doc
./2/t r e.txt
./2/sub/hello.doc
./2/sub/hejsan.doc

Pemakaian:

$ ./differ-r
Usage: compare files in two directories including subdirectories
         ./differ-r <source-dir> <target-dir> <pattern>
Example: ./differ-r  subdir-1     subdir-2     "*.txt"

Berlari differ-r:

Baris diffperintah yang dilakukan dicetak dengan teks hijau dan output, ketika tidak ada kecocokan yang dicetak dengan teks standar (putih di atas hitam pada tangkapan layar berikut).

masukkan deskripsi gambar di sini

$ ./differ-r 1 2 "*.doc"
diff "1/two.doc" "2/two.doc"
diff "1/sub/only-one.doc" "2/sub/only-one.doc"
diff: 2/sub/only-one.doc: No such file or directory
diff "1/sub/hello.doc" "2/sub/hello.doc"
2d1
< world
diff "1/sub/hejsan.doc" "2/sub/hejsan.doc"

$ ./differ-r 1 2 "*.txt"
diff "1/ett.txt" "2/ett.txt"
2c2
< stabben
---
> farsan
diff "1/t r e.txt" "2/t r e.txt"
1c1
< t r e
---
> 3
$ 

$ ./differ-r 1 2 "*"
diff "1/ett.txt" "2/ett.txt"
2c2
< stabben
---
> farsan
diff "1/two.doc" "2/two.doc"
diff "1/t r e.txt" "2/t r e.txt"
1c1
< t r e
---
> 3
diff "1/sub/only-one.doc" "2/sub/only-one.doc"
diff: 2/sub/only-one.doc: No such file or directory
diff "1/sub/hello.doc" "2/sub/hello.doc"
2d1
< world
diff "1/sub/hejsan.doc" "2/sub/hejsan.doc"

$ ./differ-r 2 1 "*"
diff "2/ett.txt" "1/ett.txt"
2c2
< farsan
---
> stabben
diff "2/two.doc" "1/two.doc"
diff "2/t r e.txt" "1/t r e.txt"
1c1
< 3
---
> t r e
diff "2/sub/hello.doc" "1/sub/hello.doc"
1a2
> world
diff "2/sub/hejsan.doc" "1/sub/hejsan.doc"

rsync dengan filter

Jika Anda tidak perlu mendapatkan output yang menggambarkan perbedaan, hanya tahu file mana yang berbeda atau hilang (sehingga rsyncingin menyalinnya), Anda dapat menggunakan baris perintah berikut.

rsync --filter="+ <pattern>" --filter="+ */" --filter="- *"--filter="- */"  -avcn <source directory>/ <target directory>

Demo

$ rsync --filter="+ *.doc" --filter="+ */" --filter="- *"  -avcn 1/ 2
sending incremental file list
./
sub/
sub/hello.doc
sub/only-one.doc

sent 276 bytes  received 35 bytes  622.00 bytes/sec
total size is 40  speedup is 0.13 (DRY RUN)

sent 360 bytes  received 41 bytes  802.00 bytes/sec
total size is 61  speedup is 0.15 (DRY RUN)
olle@bionic64 /media/multimed-2/test/test0/temp $ rsync --filter="+ *.txt" --filter="+ */" --filter="- *" -avcn 1/ 2
sending incremental file list
./
ett.txt
t r e.txt
sub/

sent 184 bytes  received 29 bytes  426.00 bytes/sec
total size is 21  speedup is 0.10 (DRY RUN)

Jika Anda ingin output bersih tanpa mengomentari baris dan tanpa direktori, Anda dapat grepoutput seperti itu,

$ pattern="*.doc"; rsync --filter="+ $pattern" --filter="+ */" --filter="- *"  -avcn 1/ 2 | grep "${pattern/\*/.\*}"
sub/hello.doc
sub/only-one.doc

Shellscript rsync-diff

One-liner ini dapat dibuat menjadi perintah inti dari sebuah shellscript rsync-diff.

#!/bin/bash

LANG=C

if [ $# -ne 3 ]
then
 echo "Usage: compare files in two directories including subdirectories"
 echo "         $0 <source-dir> <target-dir> <pattern>"
 echo "Example: $0  subdir-1     subdir-2     \"*.txt\""
 exit
fi

pattern="$3"; rsync --filter="+ $pattern" --filter="+ */" --filter="- *" \
 -avcn "$1"/ "$2" | grep "${pattern//\*/.\*}" | grep -v \
  -e '/$' \
  -e '^sending incremental file list$' \
  -e '^sent.*received.*sec$' \
  -e '^total size is.*speedup.*(DRY RUN)$'
sudodus
sumber
0

Karena Anda menyebutkan "Jelas tidak wajib menggunakan diff",

Ini harus melakukan pekerjaan untuk Anda berbaur mudah dikonfigurasi untuk jenis file apa yang diabaikan:

masukkan deskripsi gambar di sini

Selain itu alternatif lain adalah menulis skrip sederhana yang akan ditransfer dari daftar putih ke daftar hitam dan kemudian daftar hitam akan diteruskan ke diff dengan --excludeopsi.

JammingThebBits
sumber
tag yang diperbarui untuk menambahkan 'command-line'
Marcus Junius Brutus
0

Dengan substitusi perintah pendukung shell, Anda dapat menggunakan satu-liner berikut (seperti yang sudah dicatat oleh @JammingThebBits):

diff -r dir-a dir-b --exclude-from=<( \
find dir-a dir-b -type f -not \( -name '*.xml'  -or -name '*.java' \) \
| sed 's:^.*/\([^/]*\)$:\1:' \
)

Ini bekerja seperti ini: findmencari file yang tidak menarik, sedmengekstrak nama dasarnya (berjalan basenamesangat lambat jika Anda memiliki banyak file) dan menempatkannya dalam file sementara ; file seperti itu kemudian diteruskan ke diffmenyuruhnya untuk mengecualikan mereka dari perbandingan (double exclusion = inclusion).

Jika Anda tidak memiliki substitusi perintah, letakkan sedoutput dalam file dan berikan secara eksplisit diff.

Dalam contoh saya hanya mencari file XML dan JAVA, ubah sesuai kebutuhan dengan memisahkannya dengan OR.

Corrado
sumber