Existuje způsob, jak mohu provést rekurzivní porovnání dvou adresářů, ale pouze porovnat (na jejich příslušných místech) soubory, které odpovídají konkrétnímu názvu souboru nebo predikátu typu souboru?
Např. Chtěl bych něco udělat jako
diff -r dir-a dir-b -filenames *.java, ivy.xml, build.xml
… nebo ještě lépe:
diff -r dir-a dir-b -filetype text
Je zřejmé, že použití diff
není povinné jak předpokládám zaklínadlo s find
a -exec diff
by také mohlo stačit (jen nevím, jak vygenerovat doplňkové cesty k souborům v druhém případě).
Přijatá odpověď:
Shellscript differ-r
Tento skript shellu může provádět rekurzivní porovnání dvou adresářů, ale pouze porovnávat (na jejich příslušných místech) soubory, které odpovídají konkrétnímu souboru nebo vzoru typu souboru.
#!/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 {} +
Ukázka
Soubory:
$ 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
Použití:
$ ./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"
Spuštění differ-r
:
Provedený diff
příkazové řádky jsou vytištěny zeleným textem a výstup, pokud není shoda, je vytištěn s výchozím textem (bílá na černém na následujícím snímku obrazovky).
$ ./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
s filtrem
Pokud nepotřebujete získat žádný výstup popisující rozdíl, zjistěte pouze, které soubory se liší nebo chybí (takže rsync
chcete zkopírovat), můžete použít následující příkazový řádek.
rsync --filter="+ <pattern>" --filter="+ */" --filter="- *"--filter="- */" -avcn <source directory>/ <target directory>
Ukázka
$ 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)
[email protected] /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)
Pokud chcete čistý výstup bez řádků s komentářem a bez adresářů, můžete grep
výstup takto,
$ pattern="*.doc"; rsync --filter="+ $pattern" --filter="+ */" --filter="- *" -avcn 1/ 2 | grep "${pattern/\*/.\*}"
sub/hello.doc
sub/only-one.doc
Shellscript rsync-diff
Tento jednořádkový řádek lze vytvořit jako základní příkaz shellscriptu 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)$'