물론 나는 간단한 것을 놓치고 있지만 그것은 나를 미치게 만듭니다. 원격 파일을 현재 로컬 디렉터리로 SCP로 보내려고 합니다. 원격 경로에 공백이 있습니다. 파일에서 읽기 때문에 스크립트에서 실행하고 경로를 변수에 넣어야 합니다.
문제는 어떻게 이스케이프를 시도하더라도 "파일 또는 디렉터리를 찾을 수 없습니다"라는 오류가 계속 발생한다는 것입니다. -v
명령에 옵션을 추가 scp
하고 복사하여 붙여넣으면 명령이 작동하지만 거기에 변수가 있으면 폭발합니다.
경로를 작성하면 제대로 작동하지만 경로를 변수에 넣으려고 하면 작동이 중단됩니다. 하드코딩된 문자열을 이스케이프하는 것에 대한 비슷한 질문이 많이 있지만 파일 경로에 공백이 있는 변수를 사용하는 질문은 찾을 수 없습니다.
파일 경로는 다음과 같습니다.
/home/myUser/databases/SONIC BOATS LTD./database-1.11-2019-12-30-09-40.zip
verbose 를 실행하면 scp
이 줄은 sending command
다음을 인쇄합니다.
scp -f /home/myUser/databases/SONIC\\ BOATS\\ LTD./database-1.11-2019-12-30-09-40.zip .
해당 줄을 스크립트에 붙여넣고 실행하면 작동합니다. 그렇다면 변수가 있는 스크립트에서 실행하면 왜 작동하지 않습니까?
내 변수는 다음과 같이 인쇄됩니다.
DB_ARC_FILENAME:
/home/myUser/databases/SONIC BOATS LTD./database-1.11-2019-12-30-09-40.zip
ESC_DB_ARC_FILENAME
/home/myUser/databases/SONIC\ BOATS\ LTD./database-19.11-2019-12-30-09-40.zip
내 스크립트 코드 조각:
while read DB_ARC_FILENAME
do
# Escape spaces in the files name
ESC_DB_ARC_FILENAME=${DB_ARC_FILENAME//\ /\\\ }
# Copy the database file to the local system
scp -v [email protected]:"$ESC_DB_ARC_FILENAME" .
...
done < uploadedDatabaseFileList
다음은 내가 실행할 때 얻는 결과입니다.
debug1: Sending command: scp -v -f /home/myUser/databases/SONIC\\ BOATS\\ LRD./database-1.11-2019-12-30-09-40.zip
debug1: client_input_channel_req: channel 0 rtype exit-status reply 0
debug1: client_input_channel_req: channel 0 rtype [email protected] reply 0
: No such file or directoryer/databases/SONIC BOATS LTD./database-1.11-2019-12-30-09-40.zip
debug1: channel 0: free: client-session, nchannels 1
: No such file or directoryes/SONIC BOATS LTD./database-1.11-2019-12-30-09-40.zip
debug1: fd 0 clearing O_NONBLOCK
debug1: fd 1 clearing O_NONBLOCK
Transferred: sent 2836, received 2704 bytes, in 0.8 seconds
Bytes per second: sent 3678.9, received 3507.7
debug1: Exit status 1
답변1
탈출 패턴이 올바르지 않습니다. 각 공백 앞에 백슬래시를 추가하는 이 옵션을 사용하십시오.
ESC_DB_ARC_FILENAME="${DB_ARC_FILENAME// /\\ }"
테스트 시나리오(중간 $HOME
):
file='the date.txt'
date > "$file"
scp -vp localhost:"$file" td; ls -l td; rm -f td # Fails
scp -vp localhost:"${file// /\\ }" td; ls -l td; rm -f td # Succeeds
알고 있었다. 이 오류 메시지는 이를 알려줍니다.
: No such file or directoryes/SONIC BOATS LTD./database-1.11-2019-12-30-09-40.zip
Windows 컴퓨터에서 생성된 소스 데이터 파일을 사용하고 있습니다. 물론 소스 파일에는 그러한 문자가 없지만 후행 CR은 파일 이름의 일부로 간주됩니다.
답변2
Bash 스크립트를 사용하여 공백이 포함된 원격 경로에서 파일을 복사하려고 할 때 scp
비슷한 문제가 발생했습니다 .
제가 생각해낸 해결책은 다음과 같습니다.
큰따옴표 + 옵션을 사용하세요 -T
.
scp -T user@host:"'<path-with-spaces>'" <destination>
scp -T user@host:'"<path-with-spaces>"' <destination>
scp -T user@host:"\"<path-with-spaces>\"" <destination>
참고: 옵션이 없으면 -T
이러한 명령은 protocol error: filename does not match request
이유를 자세히 설명합니다.여기.
printf의 이스케이프 경로를 사용하십시오.
source="<path-with-spaces>"
printf -v source "%q" "${source}"
scp user@host:"${source}" <destination>
참고: 이 옵션은 옵션 없이도 잘 작동 -T
하지만 단일 파일에 대해서만 작동합니다. 여러 파일의 경우 -T
옵션이 다시 필요합니다(위와 동일한 오류).