한 디렉터리에서는 파일을 찾을 수 있지만 다른 디렉터리에서는 찾을 수 없는 도구가 있습니까? [복사]

한 디렉터리에서는 파일을 찾을 수 있지만 다른 디렉터리에서는 찾을 수 없는 도구가 있습니까? [복사]

한 디렉터리에서는 이러한 파일을 찾고 다른 디렉터리에서는 찾지 않는 bash 스크립트를 작성하고 싶습니다.

아래 스크립트가 작동합니까? 그렇지 않을 때는?

for i in "$1"/*; do
    f=$(basename $i);
    if [ ! -e "$2"/"$f" ]
    then
        echo $f
    fi
done

diff 두 디렉토리의 내용 사이의 차이점을 찾는 것도 가능하다고 들었습니다 . 동일한 작업도 해결할 수 있나요?

아니면 다른 도구인가요?

감사해요.

답변1

예, 이 목적으로 사용할 수 있습니다 diff. 매우 간단합니다:

diff -rq dir1 dir2

-r옵션은 diff또한 하위 디렉터리로 재귀하도록 지시합니다. 이 -q옵션은 diff파일이 다른 경우에만 보고하도록 지시합니다.

dir1나는 일반적으로 어떤 파일이 에 있고 에 없는지 또는 그 반대의 파일을 찾고 싶을 때 dir2이 두 가지 옵션을 사용합니다 . ( -r하위 디렉터리로 재귀적으로 이동하지 않으려면 이 매개변수를 제거할 수도 있지만 두 디렉터리의 직접적인 내용만 고려하세요.)

dir1여기 에는 존재하지만 존재하지 않는 파일 dir2과 존재하지만 존재 dir2하지 않는 파일이 표시됩니다 dir1. 예를 들면 다음과 같습니다.

$ diff -rq /tmp/dir1/ /tmp/dir2/
Only in /tmp/dir1/: file1
Only in /tmp/dir2/: file2
Only in /tmp/dir2/: file3

지침 중 하나만 필요하고(예: dir1에 있지만 에는 없는 파일 dir2) 파일 이름 목록만 얻는 경우("only in..." 혼란 없이), 물론 , 등을 diff사용하여 출력을 마사지해 볼 수 있습니다. grep하지만 이 경우에는 애초에 사용하지 말고 sedStéphane Chazelas의 솔루션을 사용하는 것이 좋습니다.awkdiff

답변2

파일 이름에 개행 문자가 포함되어 있지 않으면 다음을 수행할 수 있습니다.

(export LC_ALL=C; comm -23 <(ls -A dir1) <(ls -A dir2))

dir1에서 찾을 수 없는 파일을 찾아보세요 dir2.

임의의 파일 이름의 경우 배열 빼기 기능을 사용할 수 있습니다 zsh.

dir1_files=(dir1/*(DN:t)) dir2_files=(dir2/*(DN:t))
dir1_and_not_dir2_files=(${dir1_files:|dir2_files})

( 재귀적 파일 목록 *으로 변경됨)**/*

또는 bash4.4+ 및 최신 버전의 GNU 유틸리티를 사용하십시오.

readarray -td '' dir1_and_not_dir2_files < <(
  export LC_ALL=C
  shopt -s nullglob  dotglob
  comm -z23 <(printf '%s\0' dir1/* | cut -zd/ -f2-) \
            <(printf '%s\0' dir2/* | cut -zd/ -f2-)
)

(옵션을 사용 하고 재귀 목록 으로 globstar대체 )***

LC_ALL=C이는 적어도 두 가지 이유로 필요합니다 :

  • 파일 이름에는 모든 바이트 시퀀스(0 또는 (ASCII 기반 시스템의 경우 0x2F) 값 제외 )/ 가 포함될 수 있지만comm텍스트유틸리티이므로 유효한 문자 형식을 지정하지 않는 바이트 시퀀스에 대해서는 지정되지 않은 동작이 발생합니다. 모든 문자가 단일 바이트이고 모든 바이트가 유효한 문자(정의되지 않을 수 있음)인 C 로케일에서 sp 모든 파일 이름은 유효한 텍스트입니다(또한 최대 파일 이름 길이가 일반적으로 최대 텍스트 줄 길이보다 상당히 작다는 점을 고려). .

  • 또한 comm정렬된 입력이 필요하지만 일부 로케일에서는 일부 문자가 정의되지 않은 정렬 순서를 갖거나 다른 문자와 동일하게 정렬되어 혼동을 일으킬 수 있습니다 comm. 예를 들어, en_GB.UTF-8 로케일이 있는 GNU 시스템에서는 다음과 같습니다.

      $ ls dir1 dir2
      dir1:
      

관련 정보