
$ md="-l /tmp/test/my dir"
$ ls "$md"
ls: invalid option -- ' '
Try 'ls --help' for more information.
$ md="-l \"/tmp/test/my dir\""
$ ls "$md"
ls: invalid option -- ' '
Try 'ls --help' for more information.
왜 둘 다 작동하지 않는지 궁금합니다. 감사해요. 변수의 값에는 다음이 포함됩니다.
- 옵션
-l
- 공백이 포함된 경로 이름 매개변수
- 위의 두 항목은 공백으로 구분됩니다.
내 실제 질문은 다음과 같습니다. 스크립트를 작성했습니다.myscript.sh
#! /bin/bash
old_dest=""
while getopts ":l:t" opt; do
case $opt in
l)
old_dest="--link-dest \"$OPTARG\""
;;
esac
done
rsync -a --delete "$old_dest" /path/to/source /path/to/dest
-l
옵션이 포함된 명령으로 스크립트를 호출하고 싶습니다 .
myscript.sh -l "/media/t/my external hdd/backup/old one"
스크립트에서 할당된 부분은 어떻게 작성해야 하나요 old_dest
?
답변1
명령이 작동하지 않는 이유는 인용 제거/단어 분할이 재귀적으로 적용되지 않기 때문입니다.
따라서 "$old_dest"
다음 SINGLE 매개변수로 확장됩니다.
--link-dest "/media/t/my external hdd/backup/old one"
변수가 큰따옴표로 묶여 있기 때문에 이 모든 것은 매개변수입니다. (큰따옴표는 제거되지만 큰따옴표는확장의 결과, 즉 변수 값의 일부는 삭제되지 않습니다. )
반대 방향 으로 사용하면 $old_dest
여러 인수를 얻을 수 있지만 원하는 방식은 아닙니다. 다음과 같은 5개의 매개변수를 얻게 됩니다.
--link-dest
"/media/t/my
external
hdd/backup/old
one"
매뉴얼에 설명된 대로 변수 확장을 수행한 다음 토큰화를 수행하게 되기 때문입니다. 당신은 할 수 있습니다아니요변수 확장을 얻은 다음 변수의 따옴표를 해석합니다. 그리고 따옴표는 제거되지 않으므로 최종 인수는 4자가 됩니다: one"
.
다른 답변에서 말했듯이 올바른 방법은 Bash 배열을 사용하는 것입니다.
또한 Tcl이 따옴표와 단어 분리기를 처리하는 방식이 마음에 들 수도 있습니다. 쉘 토큰화에 매우 익숙하기는 하지만 더 직관적일 수도 있지만 쉘보다 Tcl에 대해 더 많이 생각해야 합니다.
답변2
당신은 bash를 사용하고 있고 bash는 배열을 지원하므로 old_dest를 배열로 만드는 것이 좋습니다.
#! /bin/bash
old_dest=()
while getopts ":l:t" opt; do
case $opt in
l)
old_dest+=('--link-dest' "$OPTARG")
;;
esac
done
printf 'Element: %s\n' rsync -a --delete "${old_dest[@]}" /path/to/source /path/to/dest
명령과 각 인수를 별도의 줄에 표시하기 위해 rsync 호출을 printf 호출로 변경했습니다. 실행 시:
./myscript.sh -l "/media/t/my external hdd/backup/old one"
결과 :
Element: rsync
Element: -a
Element: --delete
Element: --link-dest
Element: /media/t/my external hdd/backup/old one
Element: /path/to/source
Element: /path/to/dest