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