UNIX环境下SCP多文件复制异常求助:仅复制首文件其余报错
问题排查与解决办法
我帮你分析下这个问题哈——你的scp命令之所以只复制第一个文件,核心原因是shell变量展开的逻辑坑了咱们:
当$(ssh -n $host "find /incoming -mmin -120 -name 2018*")返回多个文件路径时,shell会把这些路径用空格分隔开,然后直接替换到命令里。比如find返回/incoming/2018084session_event /incoming/2018085session_log,那展开后的命令就变成了:
scp $host:/incoming/2018084session_event /incoming/2018085session_log /incoming/
看到没?只有第一个文件前面带了$host:前缀,后面的文件被scp当成本地文件来处理了,但你本地根本没有这些文件,自然就报错了。
下面给你几个靠谱的解决方案,按推荐程度排序:
方案1:用tar管道批量传输(效率最高,支持特殊文件名)
这个方法只建立一次SSH连接,而且能完美处理带空格、特殊字符的文件名,是批量复制的首选:
ssh $host "find /incoming -mmin -120 -name '2018*' -print0 | tar -czf - --null -T -" | tar -xzf - -C /incoming/
原理说明:
- 远程端用
find ... -print0输出文件名(用null字符分隔,避免空格/换行干扰) - 远程tar把这些文件打包成压缩包,通过标准输出传到本地
- 本地tar直接解压到
/incoming/目录
方案2:循环逐个复制(逻辑简单,适合少量文件)
如果文件数量不多,用while循环逐个处理每个远程文件,确保每个文件都带上$host:前缀:
ssh -n $host "find /incoming -mmin -120 -name '2018*' -print0" | while read -r -d '' file; do scp "$host:$file" /incoming/ done
注意点:
-print0和read -r -d ''是配对使用的,专门用来处理带空格、特殊字符的文件名,避免shell解析出错。- 这个方法会为每个文件建立一次SSH连接,文件多的话效率会低一些。
方案3:用xargs批量生成scp命令(另一种批量方式)
也可以用xargs把每个远程文件路径加上$host:前缀,再传给scp:
ssh -n $host "find /incoming -mmin -120 -name '2018*' -print0" | xargs -0 -I {} scp "$host:{}" /incoming/
这个逻辑和方案2类似,但用xargs替代了while循环,同样要注意-print0和-0的配对,处理特殊文件名。
内容的提问来源于stack exchange,提问作者tbaveja
相关产品推荐
相关产品推荐

