递归使用 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 选项进行递归目录复制,但它不支持过滤文件。有几种方法可以完成您的任务,但我可能会依赖 findxargstarssh 而不是 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 会话,这太昂贵了。

【讨论】:

findscp 可能需要每个文件一个 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命令复制文件但不包括某些目录[重复]

使用scp递归复制目录时如何过滤文件?

cp scp rsync 拷贝目录文件的一些常识

windows 下使用SCP命令传递文件/文件夹到Liunx系统

砥砺前行 linux scp远程拷贝文件及文件夹

Linux scp 远程复制命令详解