다음과 같은 파일(와일드카드 또는 폴더가 있는 파일) 목록을 포함하는 입력 매개변수가 있습니다.
list="file1 dir1 **.data **.source"
이제 이 목록의 각 요소에는 접두사가 붙어야 하며 다음과 같이 --filter=+
명령 인수 목록으로 바뀌어야 합니다 rsync
.
args='--filter=="+ file1" --filter="+ dir1" --filter="+ **.data" --filter="+ **.source"'
그래서 지나갈 때$매개변수각 인수를 올바르게 수신 해야 합니다 rsync $args
. 여기서 "+" 안의 공백은 두 인수의 구분 기호가 아닌 인수의 한 문자여야 합니다.
내장된 쉘 명령만 사용하여 쉘 스크립트(bash)에서 이 작업을 어떻게 수행할 수 있습니까? 명령 은 rsync
각 매개변수를 올바르게 수신해야 합니다.
실패한 시도:
#!/bin/bash
set -f
list="file1 dir1 **.data **.source"
ct=0
arr=""
for i in $list; do
ct=$(( ct + 1 ))
arr[$ct]="--filter='+ $i'"
done
args=${arr[*]}
set -x
echo args:$args
rsync $args srcdir destdir
set +x
실행되면(폴더가 srcdir
현재 디렉터리에 존재한다고 가정) 다음이 표시됩니다.
$ ./test
+ echo args: '--filter='\''+' 'file1'\''' '--filter='\''+' 'dir1'\''' '--filter='\''+' '**.data'\''' '--filter='\''+' '**.source'\'''
args: --filter='+ file1' --filter='+ dir1' --filter='+ **.data' --filter='+ **.source'
+ rsync '--filter='\''+' 'file1'\''' '--filter='\''+' 'dir1'\''' '--filter='\''+' '**.data'\''' '--filter='\''+' '**.source'\''' a b
Unknown filter rule: `'+'
rsync error: syntax or usage error (code 1) at exclude.c(904) [client=3.1.1]
+ set +x
echo
각 매개변수가 올바르게 표시되는지 확인하세요 .
args: --filter='+ file1' --filter='+ dir1' --filter='+ **.data' --filter='+ **.source'
rsync
"+"가 인수를 완성하고 공백이 인수의 일부가 아니라 구분 기호이므로 모든 인수가 삭제되므로 명령이 각 인수를 올바르게 이해하는 것처럼 보이지 않습니다 .
답변1
파일 이름 및 패턴 목록을 단일 문자열로 사용하는 대신 이를 배열로 시작할 수 있습니다.
list=(file1 dir1 "**.data" "**.source")
그런 다음 요소를 반복합니다.
args=()
for item in "${list[@]}" ; do
args+=(--filter="+ $item")
done
--filter=+ file1
이렇게 하면 매개변수 문자열 안에 따옴표 없이 유사한 매개변수가 생성됩니다 . (따옴표가 들어가는 것을 원하지 않습니다 rsync
. 예를 들어 인용문을 포함하는 필터 규칙에 대해 불평합니다 rsync "--filter='+ foo'" ...
.)
명령에 배열을 전달할 때 다음을 "${args[@]}"
사용하여 배열 요소를 고유한 문자열로 전달해야 합니다.
rsync "${args[@]}" "$srcdir" "$destdir"
대신 "--filter=+ foo"
을 사용할 수 있을 것 같습니다 --include=foo
. 이렇게 하면 매개변수에서 문제가 있는 공백이 제거됩니다(그러나 파일 이름 패턴에서 공백이나 와일드카드는 제거되지 않습니다).
귀하의 경우에는 set -f
와일드카드를 비활성화했고 for i in $list
작동할 것입니다. 그러나 배열이 필요하기 때문에 처음에는 배열을 사용하는 것이 더 나을 것입니다.
더 중요한 것은 할당이 args=${arr[*]}
배열을 단일 문자열로 평면화한다는 것입니다. 이제 인수 내의 공백과 인수 사이의 공백은 동일하며 --filter=+ file1 --filter=+ dir1 ...
쉘은 서로 다른 유형의 공백을 구별할 수 없습니다. 따옴표가 없는 확장은 $args
모든 공백으로 분할됩니다( set -x
지저분한 따옴표를 구문 분석하려는 경우 출력에 이 내용이 표시됩니다.)
실제로 이 할당에서는 배열 사용의 모든 이점이 의미가 없게 됩니다.