源路径中带有空格的 bash 脚本出现 SCP 错误

源路径中带有空格的 bash 脚本出现 SCP 错误

当然,我错过了一些简单的事情,但这让我发疯。我正在尝试将远程文件 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

当尝试使用scpBash 脚本从包含空格的远程路径复制文件时,我遇到了类似的问题。

以下是我提出的解决方案:

使用双引号 + 选项-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再次需要选项(与上面相同的错误)。

相关内容