한 디렉터리에서는 이러한 파일을 찾고 다른 디렉터리에서는 찾지 않는 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
하지만 이 경우에는 애초에 사용하지 말고 sed
Stéphane Chazelas의 솔루션을 사용하는 것이 좋습니다.awk
diff
답변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: