使用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
之类的东西,因为它有 include
和 exclude
标志,例如:-
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 中,我正在努力尝试在操作系统上安装rsync
和 ssh
。相反,这是一个聪明的解决方法。谢谢!【参考方案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
【讨论】:
为什么对这个答案的所有反对意见?这听起来像是问题的解决方案。 因为这会复制一堆不必要的文件然后删除它们,可能会浪费很多时间。 对于一个经过多个编译步骤的程序来说,这其实很有意义。它可以在将已编译代码打包到tar
或zip
文件的步骤之前进行。相反,没有压缩(scp 进行压缩)并且“打包”的代码被复制过来。
确实@samvv(一切都取决于设置、环境)
如果文件因为空间限制而被忽略,这既浪费空间又浪费时间以上是关于使用scp递归复制目录时如何过滤文件?的主要内容,如果未能解决你的问题,请参考以下文章
java 如何递归遍历多重目录下的指定格式文件复制到目标目录并改格式