rsync
(할 수 있기 때문에) 큰 폴더 A를 B로 복사하거나 백업하고 싶습니다 .https://stackoverflow.com/a/65485164/1707015.
작동하지만 때로는 B를 정리하고 B에서 오래된 파일을 삭제하고 싶습니다(A에서 삭제된 경우).
A에서 삭제된 파일을 가져와야 합니다(B에서도 삭제할 수 있도록).
$ cat A_files.txt # for example: think the small letters as paths like ./some/path/file.yaml
a
c
d
e
f
$ cat B_files.txt
a
b
c
d
$ \grep -f A_files.txt -F -v B_files.txt
b
(백슬래시는 \
색상 등의 grep 별칭을 사용하지 않기 위한 것입니다.)
이것은 작동하지만 작은 파일에만 해당됩니다. 파일 이름당 100MB를 초과하는 파일의 경우 100GB 이상의 RAM이 필요합니다.
누군가 나에게 보다 리소스 효율적인 변형을 제공할 수 있습니까? 물론 가능합니다 rsync
. 하지만 재미나 연습 목적으로 사용하기 위한 것은 아닙니다.
답변1
목록 결합/뺄셈의 경우 표준 명령은 입니다 comm
. 정렬된 파일 라인에서 작동합니다.
B_files.txt
따라서 행이 포함되지 않은 경우 A_files.txt
:
export LC_ALL=C # for a simple and deterministic order and allow any byte
# in file names.
comm -23 <(sort A_files.txt) <(sort B_files.txt)
파일이 이미 정렬된 경우:
comm -23 A_files.txt B_files.txt
이 접근 방식(또는 귀하의 접근 방식)은 파일 이름에 개행 문자가 포함될 수 있으므로 임의의 파일 이름에는 작동하지 않습니다.철사.
GNU 시스템을 사용하는 경우 NUL을 사용하여 행 대신 레코드를 구분하고 및 옵션을 사용할 수 있습니다 -z
.sort
comm
또 다른 방법은 zsh의 배열 조합/뺄셈 연산자를 사용하는 것입니다.
cd /path/to/A || exit
A_regular_files=(**/*(ND.))
cd /path/to/B || exit
B_regular_files=(**/*(ND.))
files_in_B_but_not_in_A=(${B_regular_files:|A_regular_files})
또한 이 -x
옵션을 전달하지 않으면 grep
하위 문자열이 일치합니다 . 예를 들어 grep -F foo/bar
일치합니다.blah/foo/barrage
답변2
나는 다음을 생각해 냈습니다.
MY_SOURCE=A_files.txt
readarray -t MY_TARGET_ARRAY < B_files.txt
for LINE in "${MY_TARGET_ARRAY[@]}"; do
if ! grep -q "${LINE}" "${MY_SOURCE}"; then
echo "${LINE}";
fi;
done
아직 테스트되지 않았습니다. 누락된 문제 -x
및/또는 누락된 -F
문제 가 있을 수 있습니다 grep
.