고급 파일 필터링

고급 파일 필터링

기록, 받은 편지함, 백업이라는 세 가지 폴더가 있습니다.

백업에 존재하지 않는 모든 파일을 기록에서 받은 편지함으로 복사해야 합니다.

어떻게 해야 하나요?

답변1

예를 들어 기록에 하위 폴더가 있습니까?

for x in history/*;
do
  [[ -f backup/"$(basename "$x")" ]] || cp "$x" inbox
done

이 스크립트는 기록 폴더에 있는 모든 가능한 파일을 반복하고 해당 기본 이름(예: /bin/ls의 기본 이름은 ls임)을 추출한 후 파일이 백업 폴더에 있는지 확인하고, 그렇지 않은 경우 프로그램 복사를 실행합니다. .

답변2

이 간단한 스크립트는 세 디렉터리에 하위 디렉터리가 포함되지 않은 경우에만 작동합니다(이 경우를 처리하려면 더 복잡한 재귀 알고리즘이 필요함).

Warlock의 답변은 훌륭하지만 Warlock의 한 줄 스크립트와 비교할 때 이와 같은 스크립트의 장점은 xargs를 사용하면 복사된 모든 파일에 대해 cp 인스턴스를 생성하지 않는다는 것입니다. xargs가 셸의 명령줄 길이 제한을 충족하는 명령줄을 생성할 때마다 cp 인스턴스만 포크합니다. 이는 최신 시스템에서 큰 경향이 있으므로 역사적으로 수백 또는 수천 개의 파일이 있더라도 cp Total 인스턴스 하나만 실행할 가능성이 높습니다.

#! /bin/sh

# use tempfile(1) if available, otherwise use:
# EXCLUDEFILE="/tmp/excl.$$"
EXCLUDEFILE=$(tempfile -p excl)

# generate an exclude file, changing backup/ to history/    
find  backup/ -type f | sed -e 's:^backup/:history/:' > "$EXCLUDEFILE"

find history/ -type f -print0 | \
  grep -z -Z -F -v -x -f "$EXCLUDEFILE" | \
  xargs -0r -i{} cp {} inbox/

rm "$EXCLUDEFILE"

참고로 여기에 사용된 grep 옵션의 긴 형식은 다음과 같습니다.

grep --null-data --null --fixed-strings --invert-match \
      --line-regexp --file "$EXCLUDEFILE"

보다 간결한 형식은 다음과 같습니다.

grep -zZFvxf "$EXCLUDEFILE"

대부분의 옵션은 일반적으로 사용되거나 설명이 필요하지 않지만 그 중 세 가지는 설명이 필요할 수 있습니다.

-z--null-datagrep에게 null로 끝나는 입력(에서 find -print0) 을 예상하도록 지시 하거나 grep에게 null로 끝나는 라인(으로 파이프됨 ) 을 출력하도록 지시 하거나 grep에게 전체 전체 라인만 일치시키도록 지시하십시오
-Z.--nullxargs -0
-x--line-regexp

관련 정보