나는 bash 쉘을 사용하고 있습니다. 두 디렉터리의 파일 이름 차이를 확인하고 싶지만 해당 디렉터리의 직접 하위 디렉터리만 확인하고 싶습니다. 예를 들어, 다음과 같은 하위 파일/디렉토리가 있는 디렉토리가 있는 경우...
dir1
-> abc
-> def
-> ghi
dir2
-> abc
-> fff
-> ghi
dir2에는 dir1에는 없는 "fff"라는 이름의 파일/디렉토리가 있고 "dir1"에는 dir2에는 없는 "def"라는 하위 파일/디렉토리가 있음을 알려주는 일부 명령을 실행할 수 있기를 원합니다. 어떻게 해야 하나요?
답변1
for name in dir1/* dir2/*; do
bname=${name##*/}
if [ ! -e "dir1/$bname" ]; then
printf '"%s" not in dir1\n' "$bname"
elif [ ! -e "dir2/$bname" ]; then
printf '"%s" not in dir2\n' "$bname"
fi
done
이것은 dir1
sum 의 모든 이름을 반복합니다 dir2
. 경로 없이 $bname
이름의 기본 이름이 됩니다 .$name
(기본) 이름이 에서 발견되지 않으면 dir1
보고됩니다 . 그렇지 않으면 dir2
보고서에서 찾을 수 없습니다.
이것은 삽입된 개행 문자가 포함된 파일 이름을 처리할 수 있으며 /bin/sh
호환되는 모든 sh
쉘에서 실행되어야 합니다.
이는 두 개 이상의 디렉터리로 확장될 수 있습니다. 그리고 bash
:
dirs=( dir1 dir2 dir3 dir4 )
for dir in "${dirs[@]}"; do
for name in "$dir"/*; do
bname=${name##*/}
for tdir in "${dirs[@]}"; do
if [ ! -e "$tdir/$bname" ]; then
printf '"%s" not found in %s\n' "$bname" "$tdir"
fi
done
done
done
$ tree
.
|-- dir1
| `-- filename 1
|-- dir2
| |-- filename 1
| |-- filename 3
| `-- hello
world
`-- script.sh
$ sh script.sh
"filename 3" not in dir1
"hello
world" not in dir1
답변2
이를 위해 나는 comm -3
plain 의 출력을 정말 좋아합니다 ls
.
$ comm -3 <(ls dir1) <(ls dir2)
def
fff
첫 번째 열의 항목은 첫 번째 디렉터리에만 있고, 두 번째 열의 항목은 두 번째 디렉터리에만 있습니다. 이 -3
옵션은 두 디렉터리 모두에 공통된 항목을 표시하는 세 번째 열을 제거합니다. 또한 존재하지만 에 없는 파일 -1
만 보거나 에 존재 하지만 존재하지 않는 파일 만 보도록 지정할 수도 있습니다 .dir2
dir1
-2
dir1
dir2
ls
이렇게 하려면 옵션이 설정되어 있지 않은지 확인해야 합니다.통과하다해당 OPTIONS
구성 또는 별칭입니다. 다음과 같은 변형을 사용하면 이러한 문제를 피할 수 있습니다.
$ comm -z -3 <(cd dir1; printf "%s\0" *) <(cd dir2; printf "%s\0" *) | tr '\0' '\n'
def
fff
후자는 파일 이름의 특수 문자 문제를 방지합니다. -1
이를 또는 와 결합하여 내부에 -2
놓아 tr
두 xargs -0
파일 세트 중 하나를 추가로 처리할 수 있습니다.