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

Posted

技术标签:

【中文标题】使用scp递归复制目录时如何过滤文件?【英文标题】:How to filter files when using scp to copy dir recursively? 【发布时间】:2010-11-16 17:46:24 【问题描述】:

我需要将所有 .class 文件从服务器复制到本地,并保留所有目录。例如server:/usr/some/unknown/number/of/sub/folders/me.class 将是 /usr/project/backup/some/unknown/number/of/sub/folders/me.class 问题是,还有许多其他无用的文件,例如我不想要的 .svn-base 文件。我怎样才能过滤它们,所以我只有scp .class 文件?

【问题讨论】:

我喜欢提到的 rsync 选项。你没有提到这是否是一次性的操作,或者你是否会重复地自动化它。对于一次性操作,明智地使用 find、grep -v、xargs 和临时文件应该可以缩短工作时间。 【参考方案1】:

我可能会建议使用 rsync 之类的东西,因为它有 includeexclude 标志,例如:-

rsync -rav -e ssh --include '*/' --include='*.class' --exclude='*' \
server:/usr/some/unknown/number/of/sub/folders/ \ 
/usr/project/backup/some/unknown/number/of/sub/folders/

其他一些有用的标志:

-r 用于递归 -a 用于存档(主要是所有文件) -v 用于详细输出 -e 指定 ssh 而不是默认值(实际上应该是 ssh)

【讨论】:

无论如何要忽略其中没有 *class 文件的子文件夹? (即我不想要一堆空目录) 太棒了,这也太快了! 你能解释一下 --include,而不是 --include= 在 MAN 页面中,我可以找到关于 --include= 但不是 --include 的解释 根据 rsync 手册页,选项 -a 已经包含 -r @GrantBirchmeier --prune-empty-dirs 将删除空目录。【参考方案2】:

排除基目录中的点文件:

scp -r [!.]* server:/path/to/something

[!.]* 是一个 shell glob,它扩展到工作目录中不以点开头的所有文件。

【讨论】:

这可能是最好的答案;使用 glob 过滤文件是可行的方法。 如果您的选择像我一样仅限于 scp ,这肯定有帮助。 这表示排除像被询问的文件,但是如何实现整个目录? 对于 zsh:scp -r [\!.]* server:/path/to/something【参考方案3】:

scp 中没有过滤文件的功能。对于像这样的“高级”东西,我建议使用 rsync:

rsync -av --exclude '*.svn' user@server:/my/dir .

(这一行将rsync从远程文件夹复制到当前文件夹)

最新版本的 rsync 隧道默认自动通过 ssh 连接。

【讨论】:

【参考方案4】:

既然你可以scp你应该可以ssh, 编写以下脚本或登录并执行...

# After reaching the server of interest
cd /usr/some/unknown/number/of/sub/folders
tar cfj pack.tar.bz2 $(find . -type f -name *.class)

返回(注销)到本地服务器和scp

# from the local machine
cd /usr/project/backup/some/unknown/number/of/sub/folders
scp you@server:/usr/some/unknown/number/of/sub/folders/pack.tar.bz2 .
tar xfj pack.tar.bz2

如果您发现 $(find ...) 太长,无法将 tar 更改为,

find . -type f -name *.class | xargs tar cfj pack.tar.bz2

最后,既然你把它保存在/usr/project/backup/, 为什么要提取?只需保留tar.bz2,可能带有日期+时间戳

【讨论】:

这对我有帮助。我在 Windows 中,我正在努力尝试在操作系统上安装 rsyncssh。相反,这是一个聪明的解决方法。谢谢!【参考方案5】:

下面的文件命令。

scp `查找 . -maxdepth 1 -name "*.log" \! -name "hs_err_pid2801.log" -type f` root@IP:/tmp/test/

    IP 将是目标服务器的 IP 地址。 -为包含文件命名“*.log”。 \! -name "hs_err_pid2801.log" 用于排除文件。 。是当前的工作目录。 -type f 表示文件类型。

下面的目录命令。

scp -r `查找 . -maxdepth 1 -name "lo*" \! -name "localhost" -type d` root@IP:/tmp/test/

您可以根据需要自定义上述命令。

【讨论】:

这会将文件从本地复制到远程,问题是关于远程到本地【参考方案6】:

启用基于 ssh 密钥的身份验证后,以下脚本将起作用。

for x in `ssh user@remotehost 'find /usr/some -type f -name *.class'`; do y=$(echo $x|sed 's/.[^/]*$//'|sed "s/^\/usr//"); mkdir -p /usr/project/backup$y; scp $(echo 'user@remotehost:'$x) /usr/project/backup$y/; done

【讨论】:

【参考方案7】:

如果你确实想使用scp,有一个间接的方法。假设我们要将本地文件夹'/src'下的所有.jpg文件复制到远程服务器10.1.1.2中的文件夹'/dst' :

#make a clean temp folder
mkdir /tmp/ttt
#copy all .jpg file and retain folder structure as-is
find /src -type f -name *.jpg -exec cp --parents \\ /tmp/ttt \;
#copy to remote target folder as-is and retain original time attributes
scp -rp /tmp/ttt/* 10.1.1.2:/dst
#if copy ok, remove temp folder
rm -rf /tmp/ttt

【讨论】:

【参考方案8】:
scp -i /home/<user>/.ssh/id_rsa -o "StrictHostKeyChecking=no" -rp /source/directory/path/[!.]* <target_user>@<target_system:/destination/directory/path

【讨论】:

语言解释和代码也很有帮助【参考方案9】:

    将你的源文件夹复制到somedir

    cp -r srcdir somedir

    删除所有不需要的文件:

    find somedir -name '.svn' -exec rm -rf \+

    somedir启动scp

【讨论】:

为什么对这个答案的所有反对意见?这听起来像是问题的解决方案。 因为这会复制一堆不必要的文件然后删除它们,可能会浪费很多时间。 对于一个经过多个编译步骤的程序来说,这其实很有意义。它可以在将已编译代码打包到tarzip 文件的步骤之前进行。相反,没有压缩(scp 进行压缩)并且“打包”的代码被复制过来。 确实@samvv(一切都取决于设置、环境) 如果文件因为空间限制而被忽略,这既浪费空间又浪费时间

以上是关于使用scp递归复制目录时如何过滤文件?的主要内容,如果未能解决你的问题,请参考以下文章

如何递归复制目录并在 Perl 中过滤文件名?

linux远程复制文件命令小总结

linux远程复制文件命令小总结

java 如何递归遍历多重目录下的指定格式文件复制到目标目录并改格式

如何获取 Net::OpenSSH->scp_get() 方法复制的文件列表

scp命令