批量移动大文件时出现Argument list too long错误求助
嘿,这个问题我太熟了!你遇到的是bash里经典的「参数列表过长」错误——当你一次性传递给命令的文件名太多,超过了系统允许的命令行参数长度上限,就会触发这个报错。你的原始命令里,find输出的文件数量太多,xargs试图把所有文件名一次性传给mv,直接撞了上限。下面给你几个靠谱的解决方案:
方案1:用find自带的-exec选项(最推荐)
find的-exec可以直接处理找到的文件,避免通过管道传递参数时的长度限制,而且还能完美处理带空格/特殊字符的文件名。
高效批量版本(优先用这个)
如果你的mv支持-t选项(大部分现代Linux发行版都支持),可以把目标目录放在前面,让find批量传递文件:
find ./ -name "sm20180416*" -exec mv -t /ora_arch/ssmfep_backup/ {} +
这里的+表示find会尽可能多地把文件打包成一批传给mv,效率和xargs差不多,但完全不会触发参数过长问题。
兼容旧系统版本
如果你的mv不支持-t,可以用逐个处理的方式(效率稍低,但兼容性拉满):
find ./ -name "sm20180416*" -exec mv {} /ora_arch/ssmfep_backup/ \;
这里的\;表示find会对每个找到的文件单独执行一次mv,虽然慢一点,但绝对不会有参数长度问题。
方案2:给xargs加参数限制
如果你还是想用xargs,可以通过-n或-L选项限制每次传递给mv的文件数量,比如每次传100个:
find ./ -name "sm20180416*" | xargs -n 100 mv -f -t /ora_arch/ssmfep_backup/
-n 100告诉xargs每次最多传递100个文件名给mv,这样就不会超过参数长度上限了。同样,-t选项让目标目录在前,避免参数顺序问题。
方案3:用rsync处理(适合复杂场景)
如果你的文件名里有空格、换行符等特殊字符,或者需要跨文件系统移动,rsync是个更稳妥的选择,而且自带移除源文件的功能:
find ./ -name "sm20180416*" -print0 | rsync -av --files-from=- --from0 --remove-source-files ./ /ora_arch/ssmfep_backup/
-print0让find用空字符分隔文件名,避免特殊字符干扰--from0告诉rsync用空字符解析输入的文件名--remove-source-files会在成功复制后删除源文件(注意:只有当文件完全复制成功才会删除,比mv更安全)
小提醒
你的原始命令里find ./ -name f看起来可能是个笔误?后面mv的是sm20180416*,所以应该把find的-name改成"sm20180416*",不然会匹配所有名为f的文件,而不是你想要的前缀文件哦。
内容的提问来源于stack exchange,提问作者Faiz

