이것을 호출하는 스크립트가 있습니다
find "/mnt/Data/Shared/$1" -type d -exec bash -c 'fixperm "'${1}'" "fd" "$0"' {} \;
$1은 디렉토리입니다. 이름에 공백이 없으면 작동하지만, 공백이 있으면 실패하고 오류를 반환합니다. "00_Office Test"를 사용하여 테스트
Test" "fd" "$0": -c: line 0: unexpected EOF while looking for matching `"'
Test" "fd" "$0": -c: line 1: syntax error: unexpected end of file
경로에 공백 앞에 \가 없기 때문에 그럴 수도 있다고 생각했지만 문제가 해결되지 않았습니다. 나는 여기서 사소한 것을 놓치고 있다고 확신합니다.
답변1
이는 작은따옴표 밖에 나타나기 때문입니다 ${1}
. 즉, 쉘이 보기 전에 확장되고 토큰화된다는 의미입니다 find
. StackExchange의 구문 강조 표시를 통해 이를 명확하게 알 수 있습니다. 단어 분리를 방지하려면 큰따옴표를 사용하세요.
또한 호출을 사용하면 bash -c
따옴표를 직접 처리해야 하지만 파일 이름에 큰따옴표가 포함되어 있으면 문제가 발생할 수 있습니다. 사용하지 말고 매개변수를 직접 전달하세요.
find "/mnt/Data/Shared/$1" -type d -exec fixperm "$1" fd {} \;
답변2
따옴표 없이 사용하고 있기 때문입니다 ${1}
.
인용하다
견적 문제를 해결하는 것은 상당히 복잡할 수 있습니다.
'${1}'
으로 바꾸는 것이 '"${1}"'
도움이 될 것 같습니다.
비교하다:
$ set -- "ab cd"; bash -c 'printf "<%s> " '${1}' "fd" "$0"'
<ab>
그리고:
$ set -- "ab cd"; bash -c 'printf "<%s> " '"${1}"' "fd" "$0"'
<ab> <cd> <fd> <bash>
그러나 쉘 "인용 제거"는 여전히 변수 값에 적용됩니다.
해결 방법으로 다음을 사용할 수 있습니다.'"${1@Q}"'
$ set -- 'a"b c"d'; bash -c 'printf "<%s> " '"${1}"' "fd" "$0"'; echo
<ab cd> <fd> <bash> # quotes got lost.
$ set -- 'a"bc"d'; bash -c 'printf "<%s> " '"${1@Q}"' "fd" "$0"'; echo
<a"b c"d> <fd> <bash> # correct quotes.
그러나 이는 명령에 포함된 두 개의 셸 노출 루프(먼저 명령 find
, 다음 bash -c
명령)에서는 작동하지 않습니다.
$ mkdir 'a"bc"d' 'a"b c"d' 'a"bcd'
$ set -- 'a"bc"d'; find "./$1" -type d -exec bash -c 'printf "<%s> " fixperm "'"${1}"'" "fd" "$0"' {} >
<fixperm> <abcd> <fd> <./a"b c"d>
$ set -- 'a"b c"d'; find "./$1" -type d -exec bash -c 'printf "<%s> " fixperm "'"${1}"'" "fd" "$0"' {} >
<fixperm> <ab> <cd> <fd> <./a"b c"d>
$ set -- 'a"bcd'; find "./$1" -type d -exec bash -c 'printf "<%s> " fixperm "'"${1}"'" "fd" "$0"' {} \;
./a"bcd: -c: line 0: unexpected EOF while looking for matching `"'
./a"bcd: -c: line 1: syntax error: unexpected end of file
옳은
$1
그러나 실제로 일어나는 일은 $1
호출하는 스크립트의 매개변수와 호출하는 쉘의 의미 사이에 혼동이 있는 것 같습니다.bash -c
은행:
find "/mnt/Data/Shared/$1" -type d -exec bash -c '
fixperm "'"${1}"'" "fd" "$0"' {} \;
읽어야합니다:
find "/mnt/Data/Shared/$1" -type d -exec bash -c '
fixperm "$1" "fd" "$2"' bash-shell "$1" {} \;
이는 인용을 더욱 직접적이고 강력하게 만듭니다.
단순한
스크립트 내에서 실행할 루프나 기타 복잡한 기능이 없으면 bash -c
거의 모든 참조를 제거하고 작성할 수 있습니다.
dir="/mnt/Data/Shared"
find "$dir/$1" -type d -exec fixperm "$1" fd {} \;