특정 파일 형식에 대해서만 diff -r


12

두 디렉토리의 재귀 diff를 수행 할 수 있지만 특정 파일 이름 또는 파일 유형 술어와 일치하는 파일 만 비교할 수 있습니까?

예를 들어 다음 과 같은 일을 하고 싶습니다

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

... 또는 더 나은 :

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

분명히이 사용하는 필수 아닌 diff내가 가진 주문을 가정으로 find하고 -exec diff또한 트릭을 (난 그냥 후자의 경우에 보완 filepaths을 생성하는 방법을 모른다) 할 수 있습니다.


3
패턴과 일치하는 파일을 제외하는 옵션이 있는데 패턴과 일치하는 파일 만 포함하는 옵션이 표시되지 않습니다.
Barmar

1
디렉토리 비교와 관련된 모든 옵션은 gnu.org/software/diffutils/manual/html_node/
Barmar

1
링크 와 Sérgio 답변을 참조하십시오.
yehudahs

답변:


1

셸 스크립트 differ-r

이 쉘 스크립트는 두 디렉토리의 재귀 diff를 수행 할 수 있지만 특정 파일 이름 또는 파일 유형 패턴과 일치하는 파일 만 (해당 위치에서) 비교합니다.

#!/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)$'

0

"확실히 diff를 사용해야하는 것은 아닙니다"라고 언급 했으므로,

당신이이 일을해야 융합 무시하는 파일 유형의 종류 무엇을 위해 쉽게 구성 :

여기에 이미지 설명을 입력하십시오

또한 다른 대안은 화이트리스트에서 블랙리스트로 전송하고 그 후에 블랙리스트가 --exclude옵션으로 diff로 전달되는 간단한 스크립트를 작성하는 것 입니다.


'명령 줄'을 추가하기 위해 업데이트 된 태그
Marcus Junius Brutus

0

쉘이 명령 대체 를 지원하면 이미 @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로 구분하여 필요에 따라 파일을 변경하십시오.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.