当然,我错过了一些简单的事情,但这让我发疯。我正在尝试将远程文件 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
当尝试使用scp
Bash 脚本从包含空格的远程路径复制文件时,我遇到了类似的问题。
以下是我提出的解决方案:
使用双引号 + 选项-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
再次需要选项(与上面相同的错误)。