확장되지 않은 폴더 목록의 for 루프

확장되지 않은 폴더 목록의 for 루프

Bash 셸에서 백업 스크립트에 대한 명령줄을 생성하려고 합니다.

간단한 예:

EXCLUDES="/home/*/.cache/* /var/cache/* /var/tmp/* /var/lib/lxcfs/cgroup/*"; 
for FOLDER in $EXCLUDES; do printf -- '--exclude %b\n' "$FOLDER" ; done

결과는 다음과 같습니다.

--exclude '/home/*/.cache/*' --exclude '/var/cache/*' --exclude '/var/tmp/*' --exclude '/var/lib/lxcfs/cgroup/*'

그러나 문제는 이러한 폴더가 셸에서 확장된다는 것입니다. echo/printf/quoting/IFS를 사용하여 많은 예제를 시도했지만 올바른 결과가 없습니다.

이 문제에 대한 해결책이 있습니까?

답변1

경로 이름 목록, 파일 이름 전역 변수가 있는 경로 이름 목록, 또는 반복하거나 일부 명령에 대한 인수 목록으로 사용하려는 일반 목록을 지정해야 할 때마다 배열을 사용하십시오.

배열이 아닌 문자열을 사용하는 경우 공백이 있는 항목을 처리할 수 없습니다(문자열에서 공백을 구분 기호로 사용하고 있기 때문입니다). 또한 토큰화(변수를 인용하지 않고 확장)를 호출해야 하므로 문자열 내용을 반복하는 것도 어렵습니다. 그러나 이로 인해 set -f.

대부분의 쉘에서는 일반 쉘이라도 /bin/sh배열을 사용할 수 있습니다. 에서는 sh위치 인수 배열( $@)을 사용합니다.

bash경우 인용된 문자열 배열을 사용하세요.

excludes=( '/home/*/.cache/*'
           '/var/cache/*'
           '/var/tmp/*'
           '/var/lib/lxcfs/cgroup/*' )

그 다음에,

rsync_opts=( --verbose --archive )
for excl in "${excludes[@]}"; do
    rsync_opts+=( --exclude="$excl" )
done

후에,

rsync "${rsync_opts[@]}" source/ target

위의 모든 변수 확장에서는 참조가 중요합니다. 확장 "${array[@]}"(및 "$@"그 아래)으로 인해 관련 배열의 개별적으로 인용된 요소 목록이 생성됩니다(단, 큰따옴표 안에만 해당됩니다!).

모든 /bin/sh쉘의 경우:

set -- '/home/*/.cache/*'  \
       '/var/cache/*'      \
       '/var/tmp/*'        \
       '/var/lib/lxcfs/cgroup/*'

for excl do
    set -- "$@" --exclude="$excl"
    shift
done
set -- --verbose --archive "$@"

rsync "$@" source/ target

관련 정보