Bash: 생성된 배열을 인수 목록으로 실행하시겠습니까?

Bash: 생성된 배열을 인수 목록으로 실행하시겠습니까?

borgbackup을 사용할 때 이 문제가 발생했지만 응답이 동일하므로 rsync예제에서는 이를 사용하겠습니다.

각 매개변수에 접두사를 추가하여 매개변수 배열을 만든 다음 해당 배열을 에 할당하고 싶지만 존재하지 않는 것처럼 동작합니다 rsync.rsync

다음 스크립트를 사용하세요.

#!/usr/bin/env bash
#

declare -a exclude_String
for excludestr in $(cat ./list); do
    exclude_String+=(--exclude=$excludestr)
done
rsync "${exclude_String[@]}" . $Destination

그리고 ./list:

'/home/*'
'*.vim*'

실행 중인 프로세스 중 A가 ps매개변수를 올바르게 표시합니다.

/usr/bin/rsync --exclude='*.vim*' --exclude='/home/*' . DESTINATION

하지만 rsync여전히 그 사람들이 거기 없는 것처럼 행동합니다. 내가 찾은이 문제주제와 관련하여 다음을 시도합니다.

#!/usr/bin/env bash
#

declare -a exclude_String
exclude_String+=(--exclude='/home/*')
exclude_String+=(--exclude='*.vim*')

rsync "${exclude_String[@]}" . $Destination

이것은 실제로 작동합니다.

나는 아직 쉘 확장이나 기타 등등에 대해 많이 알지 못합니다. 뭔가를 찾을 수 있는지 확인하기 위해 여기저기서 인용과 큰따옴표를 사용해 보았지만 운이 없었습니다.

이를 달성하는 방법에 대한 아이디어가 있습니까?

답변1

파일에 실제로 '/home/*', 및 따옴표가 포함되어 있으면 따옴표가 excludestr루프의 값에 나타난 다음 사용자가 제공한 인수에 나타납니다 rsync. 이 경우 이는 쉘 명령의 일부가 아니며 명령 대체의 확장된 값의 일부일 뿐입니다.

반면에 , exclude_String+=(--exclude='/home/*')이제 따옴표로 묶으 십시오.셸 명령의 일부이며 명령 처리 중에 삭제됩니다. ( *일반 캐릭터를 만드는 효과가 있습니다.)

rsync실제로 제외 패턴의 일부로 따옴표를 예상하거나 처리하지 않으며, 단지 이를 다른 문자로 취급하고 이름에 따옴표가 포함된 파일을 제외합니다. 따라서 일부 파일의 데이터로 제외 패턴이 있는 경우 따옴표를 포함해서는 안 됩니다.

for x in $(cat file)또한 대신 을 사용 while IFS= read -r line; do ...; done < file하거나 이 경우에는 을 사용하세요 mapfile -t exclude_String < file. 이 명령 대체는 cat단어 분리를 호출하므로 공백이 포함된 제외 패턴을 사용할 수 없습니다. 또한 반복되는 단어 목록에서 패턴의 globbing을 즉시 호출합니다 for. 당신이 원하는 것이 아닌가요?


일반적으로 말하면 필요한 것은 다음과 같습니다.

excludes=()
while IFS= read -r line; do 
    excludes+=(--exclude="$line")
done < ./list 
rsync "$flags" "${excludes[@]}" . "$destination"

./list제외할 패턴 만 포함 :

/home/*
*.vim*

"$line"(안 주위의 따옴표는 +=(--exclude="$line")쉘이 --exclude=something현재 디렉토리에서 호출된 파일을 글로빙하는 것을 방지합니다.)

이 경우 다음을 rsync사용할 수도 있습니다 --exclude-from.

rsync "$flags" --exclude-from=./list . "$destination"

루프를 제공하기 위해 파일보다 더 복잡한 것을 사용하려는 경우 프로세스 대체를 사용할 수 있습니다.

while IFS= read -r line; do
    excludes+=(--exclude="$line")
done < <(some command that produces the exclude patterns)

또한보십시오:내 변수가 하나의 "읽는 동안" 루프에서는 로컬이지만 겉보기에 유사한 다른 루프에서는 로컬이 아닌 이유는 무엇입니까?

답변2

Ilkachu가 설명했듯이, 문제는 작은따옴표가 패턴의 일부가 되어서는 안 되며, 쉘 컨텍스트에서 패턴을 작성하면 쉘이 이를 제거한다는 것입니다.

그러나 파일에서 패턴을 명시적으로 읽는 프로세스를 우회할 수 있는 것처럼 보입니다.

rsync --exclude-from=./list source/ target

사용하면 --exclude-from=FILENAME지정된 rsync에서 제외 패턴을 읽습니다 FILENAME. 이 작업을 수행할 때 패턴에 작은따옴표를 포함하면 안 됩니다.

관련 정보