저는 간단한 bash 스크립트를 갖고 있습니다. 기본적으로 파일이 원격 시스템에 존재하는지 확인하고 싶습니다. 이 작업을 수행하는 방법에 대한 많은 예를 찾았지만 누락된 구성 요소는 이를 수행하는 방법입니다.공간평가되는 경로 및/또는 파일 이름에 있습니다.
#!/bin/bash
HOST=server.local
DIR=/foo/bar
FILE="Foo Bar File With Spaces"
if ssh $HOST [[ -f ${DIR}/${FILE} ]]
then
echo "The file exists"
else
echo "The file doesn't exist."
fi
그래서 실패했습니다. 조건식에 구문 오류가 발생합니다. 그러나 FILE 변수를 다음과 같이 변경하면:
FILE="Foo\ Bar\ File\ With\ Spaces"
스크립트가 작동합니다(파일이 있기 때문에 찾습니다).
조건식의 다음 변형을 시도했습니다.
if ssh $HOST [[ -f "${DIR}/${FILE}" ]]
그리고
if ssh $HOST [[ -f "${DIR}"/"${FILE}" ]]
둘 다 작동하지 않습니다. 나는 간단한 것을 놓치고 있다는 것을 알고 있습니다. 누군가 나에게 올바른 방향을 알려줄 수 있습니까?
답변1
추가 따옴표 쌍을 추가하여 하나는 로컬 셸용이고 다른 하나는외딴쉘을 실행 중입니다 ssh
.
$ dir=/tmp; file="foo bar";
$ ssh somewhere ls -l "'$dir/$file'"
-rw-r--r-- 1 foo foo 4194304 Oct 19 18:05 /tmp/foo bar
$ ssh somewhere [[ -f "'$dir/$file'" ]] ; echo $?
0
ssh
명령이 실행되기 전에 로컬 쉘이 변수를 확장하도록 외부에서 큰따옴표를 사용하려고 합니다 . 내부 작은따옴표로 인해 원격 쉘은 특수 문자를 더 이상 확장하지 않습니다.
파일 이름에 작은따옴표가 포함되어 있지 않은 경우. 이런 경우 고민에 빠지게 됩니다.
이 문제를 해결하려면 문자열에 필요한 이스케이프 문자를 추가해야 합니다. 일부 시스템에는 이 기능이 있고 printf "%q"
새 버전의 Bash에는 이 기능이 있습니다.${var@Q}
확장비슷한 일이 이루어져야합니다.
$ dir=/tmp; file="\$foo' bar"
$ fullpath="$(printf "%q" "$dir/$file")"
$ ssh somewhere ls -l "$fullpath"
-rw-r--r-- 1 foo foo 0 Oct 19 18:45 /tmp/$foo' bar
답변2
내가 이것을 권장하는지 잘 모르겠지만 서버 관리자 및/또는 시스템/배포판이 보안에 관심이 없는 한할 수 있다(일반적으로) 소수의 환경 변수 중 하나를 남용하면 다음이 ssh
통과됩니다.
export LC_MESSAGES='path/to/file with spaces'
if ssh $host '[ -f "$LC_MESSAGES" ]' ; then ...