递归使用 scp 但不包括某些文件夹
Posted
技术标签:
【中文标题】递归使用 scp 但不包括某些文件夹【英文标题】:recursively use scp but excluding some folders 【发布时间】:2013-02-13 19:20:27 【问题描述】:假设有一些文件夹具有这些结构
/bench1/1cpu/p_0/image/
/bench1/1cpu/p_0/fl_1/
/bench1/1cpu/p_0/fl_1/
/bench1/1cpu/p_0/fl_1/
/bench1/1cpu/p_0/fl_1/
/bench1/1cpu/p_1/image/
/bench1/1cpu/p_1/fl_1/
/bench1/1cpu/p_1/fl_1/
/bench1/1cpu/p_1/fl_1/
/bench1/1cpu/p_1/fl_1/
/bench1/2cpu/p_0/image/
/bench1/2cpu/p_0/fl_1/
/bench1/2cpu/p_0/fl_1/
/bench1/2cpu/p_0/fl_1/
/bench1/2cpu/p_0/fl_1/
/bench1/2cpu/p_1/image/
/bench1/2cpu/p_1/fl_1/
/bench1/2cpu/p_1/fl_1/
/bench1/2cpu/p_1/fl_1/
/bench1/2cpu/p_1/fl_1/
....
我要做的是scp
以下文件夹
/bench1/1cpu/p_0/image/
/bench1/1cpu/p_1/image/
/bench1/2cpu/p_0/image/
/bench1/2cpu/p_1/image/
如您所见,我想递归使用scp
,但不包括所有名为“fl_X”的文件夹。 scp好像没有这个选项。
更新 scp 没有这样的功能。相反,我使用以下命令
rsync -av --exclude 'fl_*' user@server:/my/dir
但它不起作用。它只传输文件夹列表!!类似ls -R
【问题讨论】:
查看rsync,它可以使用scp
(或至少ssh
)作为其传输机制,并支持从其参数中排除某些子目录。
这样可以吗? rsync -av --exclude 'fl_*' user@server:/my/dir .
我认为这是正确的想法。我在评论中提到了这一点,因为我对自己的 rsync
技能没有足够的信心来提供明确的答案。
它不起作用。有人请看更新后的帖子
你不能scp /bench1/1cpu/p_*/image/* remotehhost:/path/2/remote
吗?祝你好运。
【参考方案1】:
虽然scp
支持使用-r
选项进行递归目录复制,但它不支持过滤文件。有几种方法可以完成您的任务,但我可能会依赖 find
、xargs
、tar
和 ssh
而不是 scp
。
find . -type d -wholename '*bench*/image' \
| xargs tar cf - \
| ssh user@remote tar xf - -C /my/dir
rsync
解决方案可以工作,但您缺少一些参数。 rsync
还需要r
开关才能递归到子目录。另外,如果您想要scp
的相同安全性,您需要在ssh
下进行传输。比如:
rsync -avr -e "ssh -l user" --exclude 'fl_*' ./bench* remote:/my/dir
【讨论】:
那么“过滤”在哪里?您正在使用tar
进行归档?
find
在我的解决方案中为您进行过滤。 tar
在本地打包你要复制的目录,在远程解包。
@jgomo3:可以,你可以在远程使用ssh
执行tar
打包文件,在本地使用tar
解包。
@alonsos:find
命令识别与提供的模式匹配的目录并将其打印出来。 xargs
命令读取输入并将它们作为tar
命令的参数,然后归档所有目录。 ssh
命令连接到远程机器并在远程机器上执行tar
,将存档解压到/my/dir
目录中。
我会添加压缩以使 网络数据 尽可能小。将tar cf
更改为tar zcf
。另请参阅superuser.com/questions/305128/…。【参考方案2】:
您可以指定GLOBIGNORE
并使用模式*
GLOBIGNORE='ignore1:ignore2' scp -r source/* remoteurl:remoteDir
您可能希望使用export GLOBIGNORE
来组合或覆盖一般规则,但对于临时使用,只需上述方法即可。 :
字符用作多个值的分隔符。
【讨论】:
或不导出:GLOBIGNORE='ignore1:ignore2' scp -r source/* remoteurl:remoteDir
【参考方案3】:
假设最简单的选项(在远程主机上安装 rsync)不可行,您可以使用 sshfs 在本地挂载远程,并从挂载目录中使用 rsync .这样您就可以使用 rsync 提供的所有选项,例如 --exclude
。
应该这样做:
sshfs user@server: sshfsdir
rsync --recursive --exclude=whatever sshfsdir/path/on/server /where/to/store
请注意,rsync 的有效性(仅传输更改,而不是所有内容)不适用于此处。这是因为要使其正常工作,rsync 必须读取每个文件的内容以查看发生了什么变化。但是,由于 rsync 仅在一台主机上运行,因此必须将整个文件传输到那里(通过 sshfs)。但是,不应传输排除的文件。
【讨论】:
有效,但--exlude param
必须放在rsync
命令之后;否则我遇到ERROR: destination must be a directory when copying more than 1 file
而且应该是exclude=param
而不是exclude param
奇怪的是,我的 rsync 版本不关心顺序。尽管如此,我还是改变了它以避免人们遇到问题。谢谢。
这比避免sshfs
部分的解决方案慢得多。只需使用rsync -av user@server:/path/on/server/ /where/to/store
【参考方案4】:
如果您使用 pem 文件进行身份验证,您可以使用以下命令(这将排除带有扩展名的文件):
rsync -Lavz -e "ssh -i <full-path-to-pem> -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null" --exclude "*.something" --progress <path inside local host> <user>@<host>:<path inside remote host>
-L 表示跟随链接(复制文件而不是链接)。 使用 pem 文件的完整路径而不是相对路径。
不推荐使用 sshfs,因为它运行缓慢。此外,上面介绍的 find 和 scp 的组合也是一个坏主意,因为它会为每个文件打开一个 ssh 会话,这太昂贵了。
【讨论】:
find
和 scp
可能需要每个文件一个 ssh
会话。但这不是我的答案。【参考方案5】:
您可以使用扩展通配符,如下例所示:
#Enable extglob
shopt -s extglob
cp -rv !(./excludeme/*.jpg) /var/destination
【讨论】:
【参考方案6】:这个对我来说很好用,因为目录结构对我来说并不重要。
scp -r USER@HOSTNAME:~/bench1/?cpu/p_?/image/ .
假设/bench1
在当前用户的主目录中。另外,将 USER 和 HOSTNAME 更改为实际值。
【讨论】:
以上是关于递归使用 scp 但不包括某些文件夹的主要内容,如果未能解决你的问题,请参考以下文章
如何使用Jenkins shell命令复制文件但不包括某些目录[重复]