![왜](https://linux55.com/image/207391/%EC%99%9C.png)
왜
정확히 동일한 파일을 포함해야 하는 두 개의 폴더가 있는데 파일 수를 보면 서로 다릅니다. 어떤 파일/폴더가 하나에는 있지만 다른 파일/폴더에는 없는지 알고 싶습니다. 아이디어는 모든 파일을 나열한 다음 comm을 사용하여 두 폴더 간의 차이점을 찾는 것입니다.
질문
/path/to/dir 및 /path/to/dir/file 형식으로 파일 및 폴더 목록을 반복적으로 만드는 방법은 무엇입니까?
중요 사항
운영 체제: Windows 11, 하위 시스템 Ubuntu 20.04.4 LTS
위치 폴더: 네트워크 드라이브 1개, 로컬 드라이브 1개
폴더 크기: 각각 ~2TB
답변1
알아채다목차Unix의 파일은 다양한 유형의 파일 중 하나일 뿐입니다. find
를 사용하여 검색 하거나 zsh glob 의 한정자를 -type d
사용할 수 있습니다. /
다른 유형문서포함하다일반 파일( -type f
, .
글로벌 한정자, 아마도 당신은문서)뿐만 아니라 심볼릭 링크( -type l
/ @
), 장치, fifo, 소켓...
파일 유형 가져오기목차, 넌 할 수있어:
find dir1/ -type d
다른 유형의 파일의 경우:
find dir1/ ! -type d
에 대해서도 마찬가지입니다 dir2
.
세 가지 주요 문제가 있습니다.
- 인쇄된 경로는
dir1/
fordir1
및dir2/
for 로 시작하므로dir2
비교가 더 어려워집니다. - 순서는 무작위입니다.
- 파일 경로는 한 줄에 하나씩 작성되지만 줄 바꿈은 파일 경로의 줄 바꿈만큼 유효합니다. 즉, 파일 경로가 여러 줄로 구성될 수 있으므로 출력을 안정적으로 후처리할 수 없습니다.
find
이러한 문제는 GNU를 통해 sort
다음 방법을 사용하여 해결할 수 있습니다 .
find dir1/ -type f -printf '%P\0' | LC_ALL=C sort -z
어디:
%P
인쇄 파일 경로dir1을 기준으로- 목록을 정렬합니다(C 로케일에서는 파일 경로가 텍스트로 구성될 필요가 없으므로).
- 0은 파일 경로에 나타날 수 없는 유일한 바이트이기 때문에 줄 대신 NUL로 구분된 레코드를 사용합니다.
이제 해당 목록을 다음과 비교할 수 있습니다.
list() {
find "$@" -printf '%P\0' | LC_ALL=C sort -z
}
echo Directory differences:
comm -z3 <(list dir1/ -type d) <(list dir2/ -type d) | tr '\0' '\n'
echo Non-directory differences:
comm -z3 <(list dir1/ ! -type d) <(list dir2/ ! -type d) | tr '\0' '\n'
comm
표시를 위해 NUL을 개행 문자로 다시 변환하고 TAB을 사용하여 파일 경로에서 다시 유효한 열을 분리하기 때문에 이 출력을 안정적으로 사후 처리할 수 없습니다 .
또는 zsh 배열로 목록을 가져오고 해당 배열 비교 연산자를 사용할 수 있습니다.
dirs_in_dir1=( dir1/**/*(ND/:s:dir1/::) )
dirs_in_dir2=( dir2/**/*(ND/:s:dir2/::) )
nondirs_in_dir1=( dir1/**/*(ND^/:s:dir1/::) )
nondirs_in_dir2=( dir2/**/*(ND^/:s:dir2/::) )
그 다음에:
dirs_only_in_dir1=( ${dirs_in_dir1:|dirs_in_dir2} )
dirs_only_in_dir2=( ${dirs_in_dir2:|dirs_in_dir1} )
nondirs_only_in_dir1=( ${nondirs_in_dir1:|nondirs_in_dir2} )
nondirs_only_in_dir2=( ${nondirs_in_dir2:|nondirs_in_dir1} )
그리고 이 배열 을 olumn print
에 넣는 등의 작업을 수행합니다 .r
1
C
print -rC1 -- $array
(또는 N
옵션을 추가하여 후처리가 가능하도록 UL을 분리하였습니다 -N
.)
답변2
이 중 어떤 것도 필요하지 않습니다 diff -qr dir1 dir2
. 예를 들면 다음과 같습니다.
$ tree
.
├── dir1
│ ├── file1
│ ├── file3
│ ├── file4
│ ├── file6
│ ├── file7
│ ├── file8
│ └── subdir1
│ ├── dsaf
│ ├── sufile1
│ └── sufile3
└── dir2
├── file1
├── file2
├── file3
├── file4
├── file9
└── subdir1
├── sufile1
└── sufile3
4 directories, 16 files
이제 두 디렉터리에서 실행하면 diff -qr
( -r
"재귀"의 경우 -q
파일이 다를 때만 보고하고 실제 차이점은 보고하지 않음) 다음과 같은 결과를 얻습니다.
$ diff -qr dir1/ dir2/
Only in dir2/: file2
Only in dir1/: file6
Only in dir1/: file7
Only in dir1/: file8
Only in dir2/: file9
Only in dir1/subdir1: dsaf
즉, 파일 목록을 얻는 방법은 다음과 같습니다 find
.
$ find dir1 -type f
dir1/subdir1/dsaf
dir1/subdir1/sufile1
dir1/subdir1/sufile3
dir1/file6
dir1/file1
dir1/file8
dir1/file4
dir1/file7
dir1/file3
그런 다음 다음을 사용하여 두 디렉터리의 출력을 제거 dir1/
하고 dir2/
사용 하고 비교할 수 있습니다.sed
프로세스 교체이를 지원하는 쉘에서:
$ comm -3 <(find dir1 -type f | sed 's|dir1/||' | sort) <(find dir2 -type f | sed 's|dir2/||' | sort)
file2
file6
file7
file8
file9
subdir1/dsaf
이는 파일 이름에 개행 문자가 없다고 가정합니다. 이러한 문제를 처리해야 하는 경우 diff -r
위의 방법을 사용하면 됩니다.
답변3
노력하다
cd /path/1
find . -type d -print | sort > list1.dir
find . -type f -print | sort > list1.file
cd /path/2
find . -type d -print | sort > list2.dir
find . -type f -print | sort > list2.file
sort
동일한 순서와 더 작은diff
결과를 보장하는 데 사용됩니다.comm
- 결과를 "오염" 시키지
list1.file
않도록 절대 대상 파일 이름을 사용할 수 있습니다 .list2.file