SCP 用美元符号覆盖文件

Eld*_*ell 3 bash scp

我有这个文件:

A.class
A$1.class
A$2.class
Run Code Online (Sandbox Code Playgroud)

和一个类似的 bash 脚本:

for i in *; do
    scp "${i}" foo@bar:/tmp/;
done
Run Code Online (Sandbox Code Playgroud)

这工作正常。所有三个文件都被复制。问题在于以下几点:

for i in *; do
    scp "${i}" foo@bar:/tmp/"${i}";
    scp "${i}" foo@bar:"/tmp/${i}";
    scp "${i}" "foo@bar:/tmp/${i}";
done
Run Code Online (Sandbox Code Playgroud)

在任何一种情况下,SCP 都会复制所有文件,但复制到同一个文件A.class

有任何想法吗?谢谢!

bon*_*ing 5

Usingscp -v显示了有关 scp 工作原理的一些详细信息:

debug1: Sending command: scp -v -t /tmp/A$2.class
Sending file modes: C0644 0 A$2.class
Sink: C0644 0 A$2.class
A$2.class                                     100%    0     0.0KB/s   00:00    
Run Code Online (Sandbox Code Playgroud)

本质上,由于 scp 在 ssh 上运行,因此它需要一个 shell 来执行您的命令,并且由于$没有转义,远程 shell 解释$2为空字符串,这使得目标名称A.class.

有两种方法可以解决这个问题。首先,您可以*直接在 scp 命令中使用glob:

scp * foo@bar:/tmp/
Run Code Online (Sandbox Code Playgroud)

但是我很确定您还有其他一些需要使用循环,所以这里是如何在循环中修复它:

for i in *; do
    scp "${i}" "foo@bar:'/tmp/${i}'"
done
Run Code Online (Sandbox Code Playgroud)

检查scp -vnow的输出显示:

debug1: Sending command: scp -v -t '/tmp/A$2.class'
Run Code Online (Sandbox Code Playgroud)

成功!单引号将阻止远程 shell 执行变量扩展。

更新:由于参数被 shell 解释为参数,您可以执行以下操作:

scp foo@bar:'$(which ssh)' .
Run Code Online (Sandbox Code Playgroud)

甚至更复杂的 shell 管道会导致文件名。这不是安全问题,因为如果您可以使用 scp 连接,则可以使用 ssh 连接。但它可能会让某些人更方便。