我正在尝试复制 ksh 中不以字母“a”开头的所有文件。
从源机器复制到目标机器是工作正常:
scp -p !(a*) user@machine:/path/directory/.
但是,如果我在目标服务器上并且想要从源服务器复制,则会失败:
scp -p user@machine:/path/!(a*) .
有任何想法吗?
答案1
我同意冯布兰德的观点。 Globing 由您正在运行的 shell 处理。因此scp user@machine:/path/*
会将 /path/* 扩展到本地 /path/* 中的文件,而不是远程计算机上的文件。
然而,只是为了笑我尝试过:
scp "user@machine:/path/[regex here]" .
并且......它起作用了。尝试一下。请注意引号。非常有必要。让我们知道。
注意:远程计算机上的用户帐户可能默认使用与其他计算机不同的 shell 程序你的,因此通配符扩展的规则可能会有所不同,因此请注意。
答案2
传递给的远程名称scp
实际上被解释为远程端以空格分隔的模式列表。当您尝试复制名称包含空格的文件时,这通常会很麻烦,但在这里它很有用:scp -p 'user@machine:/path/a*' .
将复制名称以a
.
如果您引用该模式,以便远程而不是本地解释它,那么您的命令将起作用,前提是您通过了另一个障碍。该模式!(a*)
不是基本的 shell 模式,而是 ksh 扩展(如果设置适当的选项,bash 和 zsh 也支持)。因此,只有当您的远程 shell 是 ksh 时,这才有效,而如果它是其他 shell 且您exec ksh
来自.profile
或类似的 shell,则此方法无效。
除非您处于某种受限制或古老的环境中,否则最简单的方法就是忘记scp
.您希望远程文件像本地文件一样工作,因此将它们设为本地文件:使用以下命令挂载远程目录sshfs。这需要本地计算机上的 FUSE 和远程计算机上的SFTP 服务器(即启动的sftp-server
可执行文件)。sshd
mkdir ~/net/machine
sshfs user@machine:/ ~/net/machine
cp -p ~/net/machine/path/!(a*) .
答案3
这不是“使用正则表达式的 scp”,处理文件 glob 的是 shell。scp
只是得到已经扩展的文件列表。扩展发生在运行命令的机器上。
答案4
我发现,在较旧的 HP-UX 计算机(parisc 11.11)上,我必须使用 [^a]* 但是,在较新的计算机(parisc 11.31 及更新版本)上,它可以使用 !(a*)
这就是我最终得到的结果。它有效:
if [[ ${S_MACH} = "phd026a" || ${S_MACH} = "tht030a" ]]
then
scp -p -r ${S_MACH}:${S_DIR}/bin/[^a^b^c^p]* ${D_DIR}/bin/.
else
scp -p -r ${S_MACH}:${S_DIR}/bin/!((a*)|(b*)|(c*)|(p*)) ${D_DIR}/bin/.
fi