다음 코드 조각은 제가 작업 중인 더 큰 Bash 스크립트의 일부입니다.내 목적은 입력 변수를 Rsync에 매개 변수로 전달하는 것입니다.
"--exclude" 인수를 제외하고는 대부분 작동하도록 만들었습니다.
INCLUDE="/.vim*,/.git*,/.ssh,.bash_aliases,.bashrc"
rsync ${DRYRUNARG} -avzhP --delete ${SOURCE_DIRS} \
--include=${INCLUDE} \
--exclude={/VirtualBox_VMs/*/Snapshots,/snap,/Downloads,/.*} \
${MNTPNT}${DEST_DIR}
이 코드는 내 요구 사항에 매우 적합하지만 변수로 정의해야 하는 제외된 디렉터리를 계속 보고 싶습니다.
필요한 결과 코드는 다음과 같아야 합니다.
INCLUDE="/.vim*,/.git*,/.ssh,.bash_aliases,.bashrc"
EXCLUDE="/VirtualBox_VMs/*/Snapshots,/snap,/Downloads,/.*"
rsync ${DRYRUNARG} -avzhP --delete ${SOURCE_DIRS} \
--include=${INCLUDE} \
--exclude=${EXCLUDE} \
${MNTPNT}${DEST_DIR}
위의 코드는 작동하지 않습니다. 명령은 오류 없이 실행되지만 아무것도 제외할 수 없습니다.흥미롭게도 하나의 디렉터리로 EXCLUDE 변수를 정의하면 INCLUDE 변수에 사용된 것과 동일한 구조를 따르더라도 작동합니다.
나는 몇 가지 어리석은 실수를 저질렀다고 확신합니다. 어디에 있을 수 있나요?
답변1
별도의 항목 목록을 단일 문자열로 축소하지 마십시오. 이로 인해 다양한 항목을 구문 분석하기가 어렵고 구분 기호 등으로 사용되는 문자가 포함될 수 있는 항목을 처리해야 합니다. 또한 rsync
쉼표로 구분된 포함/제외 패턴 목록을 구문 분석하는 방법을 잘 모르겠습니다.
대신 배열을 사용하세요.
#!/bin/bash
INCLUDE=( '/.vim*' '/.git*' /.ssh .bash_aliases .bashrc )
EXCLUDE=( '/VirtualBox_VMs/*/Snapshots' /snap /Downloads '/.*' )
그런 다음 다음 목록의 각 항목 앞에 합계를 삽입하여 --exclude
새 목록을 만듭니다 .--include
exclude_opts=()
for item in "${EXCLUDE[@]}"; do
exclude_opts+=( --exclude="$item" )
done
include_opts=()
for item in "${INCLUDE[@]}"; do
include_opts+=( --include="$item" )
done
그런 다음 호출에서 다음 새 목록을 사용하십시오 rsync
(이것이 SOURCE_DIRS
소스 디렉터리의 배열이라고 가정).
rsync ${DRYRUNARG:+"$DRYRUNARG"} -avzhP --delete \
"${include_opts[@]}" \
"${exclude_opts[@]}" \
"${SOURCE_DIRS[@]}" \
"$MNTPNT/$DEST_DIR"
여기에서 $DRYRUNARG
설정되고 비어 있지 않으면 따옴표로 묶이고, 그렇지 않으면 명령줄의 일부가 전혀 아닙니다.
답변2
한 가지 방법은 변수를 파일 입력으로 사용하는 것입니다 --exclude-from
. 예를 들면 다음과 같습니다.
EXCLUDE_DIRS="VirtualBox_VMs
Downloads
Snapshots"
rsync -arv --exclude-from=<(printf "%s" "$EXCLUDE_DIRS";) $SOURCE $DESTINATION
답변3
나는 같은 것을 시도 해왔다. 그리고 이 질문이 혼란스럽다는 것을 알았습니다.
내가 할 수 있는 최선의 방법은 /bin/bash
쉼표로 구분된 목록을 쉼표로 구분된 목록으로 변환하는 것입니다(사용) --exclude
.
INCLUDE="/.vim*,/.git*,/.ssh,.bash_aliases,.bashrc"
EPATHS=("/VirtualBox_VMs/*/Snapshots" "/snap" "/Downloads" "/.*")
for path in "${EPATHS[@]}"; do
EXCLUDE="$EXCLUDE --exclude=$path"
done
rsync -avzhP --delete ${SOURCE_DIRS} \
--include=${INCLUDE} \
$EXCLUDE \
${MNTPNT} ${DEST_DIR}
이는 불완전하고 우아하지 않은 솔루션이지만 작동합니다.
남아있는 문제는 경로 이름에 공백을 사용하여 작동하도록 할 수 없다는 것입니다. 연결에 따옴표를 추가하려고 하면예를 들어
EXCLUDE="$EXCLUDE --exclude=\"$path\""
bash
더 많은 작은따옴표를 사용하면 문제가 해결되는 것 같습니다.
언급했듯이 set -x
이 사람은 내 친구입니다.