
$ myvar="/path to/my directory"
$ sudo bash -c "cd $myvar"
이 경우 $myvar
값의 공백으로 인한 토큰화를 방지하려면 어떻게 인용해야 합니까 myvar
?
답변1
아니요분사(따옴표가 없는 확장 시 변수를 분할하는 기능과 유사) 해당 코드에서는 as가 $myvar
인용되지 않습니다.
하지만 $myvar
. bash
따라서 그 내용은 bash 코드로 해석됩니다!
거기에 있는 공백으로 인해 여러 인수가 에 전달될 수 있습니다 cd
.분사, 그러나 쉘 구문에서 여러 토큰으로 구문 분석되기 때문입니다. 값이 이면 bye;reboot
재시작이 발생합니다!
원하는 곳은 다음과 같습니다.
sudo bash -c 'cd -P -- "$1"' bash "$myvar"
$myvar
( 이 인라인 스크립트에 첫 번째 인수로 전달하는 내용 . IFS 토큰화(및 와일드카드)를 방지하기 위해 해당 쉘에 $myvar
및 가 어떻게 인용되어 있는지 참고하세요.)$1
또는:
sudo MYVAR="$myvar" bash -c 'cd -P -- "$MYVAR"'
$myvar
(환경 변수에 전달하는 것).
물론 다음을 실행해도 유용한 것은 없습니다.오직 cd
인라인 스크립트에서( 들어가는 root
것이 가능한지 확인하는 것 외에도 ) 아마도 당신은 그 스크립트를 거기에 두고 다음과 같은 다른 일을 하고 cd
싶을 것입니다 :cd
sudo bash -c 'cd -P -- "$1" && do-something' bash "$myvar"
접근할 수 없는 디렉토리 sudo
에 접근 하는 것이 목적이라면 실제로는 작동하지 않습니다.cd
sudo sh -c 'cd -P -- "$1" && exec bash' sh "$myvar"
bash
현재 디렉토리와 상호 작용을 시작합니다 $myvar
. 그러나 쉘은 root
.
다음을 수행할 수 있습니다.
sudo sh -c 'cd -P -- "$1" && exec sudo -u "$SUDO_USER" bash' sh "$myvar"
bash
현재 디렉터리와 비특권으로 상호 작용하려는 경우, $myvar
처음에 해당 디렉터리에 들어갈 수 있는 권한이 없으면 해당 디렉터리가 현재 작업 디렉터리이더라도 해당 디렉터리에서 아무 것도 할 수 없습니다.cd
$ myvar=/var/spool/cron/crontabs
$ sudo sh -c 'cd -P -- "$1" && exec sudo -u "$SUDO_USER" bash' sh "$myvar"
bash-4.4$ ls
ls: cannot open directory '.': Permission denied
예외는 다음과 같습니다.찾다디렉터리 자체에 액세스할 수 있지만 해당 경로의 디렉터리 구성 요소 중 하나에는 액세스할 수 없습니다.
$ myvar=1/2
$ mkdir -p "$myvar"
$ chmod 0 1
$ cd 1/2
cd: permission denied: 1/2
$ sudo sh -c 'cd -P -- "$1" && exec sudo -u "$SUDO_USER" bash' sh "$myvar"
bash-4.4$ pwd
/home/stephane/1/2
bash-4.4$ mkdir 3
bash-4.4$ ls
3
bash-4.4$ cd "$PWD"
bash: cd: /home/stephane/1/2: Permission denied
엄밀히 말하면 $myvar
like (문자 그대로) 값의 경우 $(seq 10)
쉘이 해당 명령 대체를 확장할 때 단어 분리기가 발생합니다.bash
root
답변2
새로운(bash 4.4) 인용 마법을 사용하면 원하는 작업을 보다 직접적으로 수행할 수 있습니다. 더 큰 상황에 따라 다른 기술 중 하나를 사용하는 것이 더 나을 수도 있지만 제한된 상황에서는 작동합니다.
sudo bash -c "cd ${myvar@Q}; pwd"
답변3
콘텐츠를 신뢰할 수 없는 경우 $myvar
유일한 합리적인 접근 방식은 GNU를 사용하여 printf
콘텐츠의 이스케이프 버전을 만드는 것입니다.
#!/bin/bash
myvar=$(printf '%q' "$myvar")
bash -c "echo $myvar"
printf
매뉴얼 페이지에 따르면 다음 과 같습니다 .
%q
$''
ARGUMENT 인쇄할 수 없는 문자를 이스케이프하기 위해 권장되는 POSIX 구문을 사용하여 쉘 입력으로 재사용할 수 있는 형식으로 인쇄합니다 .
답변4
Stéphane Chazelas가 제안하는 것은 확실히 이를 수행하는 가장 좋은 방법입니다. sed
R..의 답변과 같이 하위 프로세스를 사용하는 대신 매개 변수 확장 구문 참조를 안전하게 사용하는 방법에 대한 답변을 제공하고 있습니다 .
myvar='foo \'\''"bar'
quote() {
printf "'%s'" "${1//\'/\'\\\'\'}"
}
printf "value: %s\n" "$myvar"
printf "quoted: %s\n" "$(quote "$myvar")"
bash -c "printf 'interpolated in subshell script: %s\n' $(quote "$myvar")"
이 스크립트의 출력은 다음과 같습니다.
value: foo \'"bar
quoted: 'foo \'\''"bar'
interpolated in subshell script: foo \'"bar