두 디렉터리를 재귀적으로 비교하면서 특정 파일 이름이나 파일 유형 조건과 일치하는 파일만 (해당 위치에서) 비교할 수 있는 방법이 있습니까?
예를 들어 나는 하고 싶다무엇좋다
diff -r dir-a dir-b -filenames *.java, ivy.xml, build.xml
...또는 더 나은 방법:
diff -r dir-a dir-b -filetype text
분명히 필수는 아닙니다. diff
주문 find
도 -exec diff
역할을 할 수 있다고 생각했기 때문입니다(후자의 경우 보조 파일 경로를 생성하는 방법을 모르겠습니다).
답변1
쉘 스크립트differ-r
이 쉘스크립트는 두 디렉터리의 재귀적 비교를 수행할 수 있지만 특정 파일 이름이나 파일 유형 패턴과 일치하는 파일(해당 위치에 있음)만 비교합니다.
#!/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 {} +
데모
문서:
$ 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
용법:
$ ./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"
달리기 differ-r
:
실행된 diff
명령줄은 녹색 텍스트로 인쇄되고, 일치하는 항목이 없으면 출력이 기본 텍스트(아래 스크린샷에서 검정색 배경에 흰색 텍스트)로 인쇄됩니다.
$ ./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
필터 포함
차이점을 설명하는 출력을 얻을 필요가 없고 어떤 파일이 다르거나 누락되었는지만 알면( rsync
복사하려는 경우) 다음 명령줄을 사용할 수 있습니다.
rsync --filter="+ <pattern>" --filter="+ */" --filter="- *"--filter="- */" -avcn <source directory>/ <target directory>
데모
$ 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)
주석 처리된 행이나 디렉토리 없이 깔끔한 출력을 원할 경우 grep
다음과 같이 출력할 수 있습니다.
$ pattern="*.doc"; rsync --filter="+ $pattern" --filter="+ */" --filter="- *" -avcn 1/ 2 | grep "${pattern/\*/.\*}"
sub/hello.doc
sub/only-one.doc
쉘 스크립트rsync-diff
이 줄은 쉘스크립트의 핵심 명령이 될 수 있습니다 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)$'
답변2
주거지원으로명령 대체다음 줄을 사용할 수 있습니다(@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:' \
)
다음과 같이 작동합니다. find
관심 없는 파일을 검색하고 sed
기본 이름을 추출한 다음( basename
파일이 많으면 매우 느리게 실행됩니다)일시적인그런 다음 해당 파일을 전달하여 diff
비교에서 제외하도록 지시합니다(이중 제외 = 포함).
명령 대체가 없으면 sed
출력을 파일에 넣고 명시적으로 diff
.
예제에서는 XML과 JAVA 파일만 검색하고 OR로 구분하여 필요에 따라 변경했습니다.