rsync를 사용하여 선택한 패턴을 제거하고 모든 파일과 일치

rsync를 사용하여 선택한 패턴을 제거하고 모든 파일과 일치

rsync특정 파일을 삭제 한다는 뜻입니다 (예:수천 개의 파일이 포함된 대규모 디렉터리를 효율적으로 삭제합니다.), 이 경우 명령줄의 패턴으로 쉘 스크립트에 할당됩니다.

이것이 지금까지 내 쉘 스크립트에 있는 것입니다.rsync_del.sh

#!/bin/bash

TARGET_DIR=${1}
shift
PATTERNS="${@}"
for patt in ${PATTERNS} ; do
    # Both do the same
    #INCLUDE_PATTERNS="${INCLUDE_PATTERNS}"' --include='\'"${patt}"\'
    INCLUDE_PATTERNS="${INCLUDE_PATTERNS} --include=\"${pattern}\""
done

EMPTYDIR=$(mktemp -d)
echo "Created empty dir ${EMPTYDIR}"
comm="rsync -a --progress --delete ${INCLUDE_PATTERNS} ${EMPTYDIR}/ ${TARGET_DIR}"
echo ${comm}
eval ${comm}

내가 사용하고 싶은 예제 패턴은 *[1-9].txt, 입니다 *000??9.txt. 문제는 실행할 때

rsync_del.sh trg_dir '*[1-9].txt'

생성된 명령줄은 다음과 같습니다.

rsync -a --progress --delete --include='*[1-9].txt' /tmp/tmp.51R9hPgkfG/ trg_dir/

(내가 보기에는 괜찮은 것 같지만) 예를 들어 유사한 파일과 일치하는 것입니다 input.dat(나는 그것을 원하지 않습니다).

이것을 구현/사용하는 올바른 방법은 무엇입니까? 패턴을 올바르게 이스케이프하는 데 문제가 있는 것 같지만 그렇게 할 수 없습니다.

echo참고: 실행할 명령을 실행하기 전에 변수에 정의해야 합니다.

답변1

실제 상황을 너무 자세히 살펴보지 않음사용여기서는 rsync대신 명령줄 생성에 중점을 둡니다 rsync.

#!/bin/bash

target=$1
shift

empty=$( mktemp -d )

trap 'rmdir "$empty"' EXIT

for pattern do
   incl+=( --include="$pattern" )
done

rsync --archive --progress --delete "${incl[@]}" --exclude='*' "$empty"/ "$target"

배열( incl위의 것) 을 사용하면 rsync같은 문자열 대신 매개변수를 개별적으로 저장할 수 있습니다. 확장은 "${incl[@]}"배열에서 개별적으로 참조되는 요소가 됩니다. 매개변수 인용은 간단하며 호출이 필요하지 않습니다 eval. 또한 모든 매개변수 확장에는 올바른 큰따옴표가 필요합니다.

코드의 문제점은 대부분 인용되지 않은 매개변수 확장을 사용한다는 것입니다. 이로 인해 쉘은 변수에 대해 토큰화 및 파일 이름 생성(세계화)을 수행합니다. 이는 공백이 포함된 패턴이나 기존 파일 이름으로 확장될 수 있는 쉘 와일드카드 패턴을 사용할 수 없음을 의미합니다.


/bin/sh구문이 더욱 간결해지기 때문입니다 .

#!/bin/sh

target=$1
shift

empty=$( mktemp -d )

trap 'rmdir "$empty"' EXIT

for pattern do
   set -- "$@" --include="$pattern"
   shift
done

rsync --archive --progress --delete "$@" --exclude='*' "$empty"/ "$target"

답변2

명시적으로 포함되지 않은 항목을 제외하여 패턴 목록을 닫아야 한다는 사실을 잊어버렸습니다. 나는 사용했다

comm="rsync -a --progress --delete ${INCLUDE_PATTERNS} --exclude=\"*\" ${EMPTYDIR}/ ${TARGET_DIR}"

관련 정보