Linux/UNIX:Shell错误中的rm,cp,mv命令参数列表过长错误

时间:2020-01-09 10:43:29  来源:igfitidea点击:

我们有一个备份服务器,大多数开发人员使用sftp或者ftp上传文件。我只需要备份最近四个星期。如果我尝试列出或者删除目录,则会出现错误,无法删除目录。我正在获取参数列表消息太长。在bash/ksh/csh/tcsh/zsh shell中执行命令时,如何解决此问题?在Linux和类似UNIX的系统下,每个命令都接受一个通常称为命令参数(或者args)的参数。例如,命令cd/etc具有一个命令行参数,即/etc。某些命令可以接受两个以上的参数,并对提供的参数起作用。例如,考虑以下cp命令:cp/etc/file1/etc/file2/etc/file3/mnt/pen

cp命令共有四个命令行参数。
该shell程序最多可容纳131072字节的命令行参数。
如果您尝试传递的数字超过该数字,则会出现如下错误:

Argument list too long
参数列表太长

请记住,每个字符都需要一个字节的存储空间。

找出命令行参数的最大长度

在Linux内核中,命令行参数的最大长度限制为 128k
要查找您的限制,请执行:

getconf ARG_MAX

输出示例:

2621440

该限制影响execve()内核函数,所有其他exec()函数(execl,execlp,execle等)都将使用该内核函数。

选项#1:在使用rm,ls,cp,mv或者任何其他Shell命令时,如何解决参数列表过长的错误问题

解决此问题的最佳方法是find和xargs命令的组合。
语法为:

find /dir/to/search -type f -name 'file-pattern' -print0 | xargs -0 -n 10 command-name
find /dir/to/search -type f -iname "*.EXT" -print0 | xargs -0 command-name
find /dir/to/search -type f -iname "*.EXT" -command

当您收到参数列表过长的错误时仅列出文件

使用以下任一语法仅列出文件

find /dir/to/search -type f -iname "*.EXT" -ls
find /nas01/data/ -type f -iname "*.doc" -ls

或者以下可移植语法:

find /nas01/data/ -name '*.doc' -exec ls {} +
## GNU/Find ##
find /nas01/data/ -type f -name '*.doc' -exec ls -l {} +

为了避免递归,请使用以下GNU查找选项:

find /nas01/data/ -name '*.doc' -maxdepth 1 -exec ls -l {} +

仅当参数列表过长错误时删除文件

语法如下:

# GNU/find and BSD/find Jan not work on older *nix
find /dir/to/search -type f -iname "*.EXT" -delete
find ~/Downloads/ -type f -iname "*.avi" -delete
find ~/Projects/ -type f -iname "*.pdf" -delete
## use xargs and rm command ##
find ~/Downloads/ -name '*.avi' -print0 | xargs -0 -n 10 rm -f

更可移植的语法:

find ~/Projects/ -name '*.pdf' -exec rm -vf {} +

为了避免递归,请使用以下GNU查找选项:

## GNU find and Jan work with bsd find too ##
find ~/Projects/ -name '*.pdf' -maxdepth 1 -exec rm -f {} +
find ~/Downloads/ -type f -iname '*.avi' -print0 | xargs -0 -n 10 rm -f

您还可以使用GNU并行命令:

## man parallel for more ##
find ~/Downloads/ -type f -iname '*.avi' -print0 | parallel -X -0 rm -vf

其中:

  • -name" * .pdf":搜索模式。
  • -type f:仅匹配文件。
  • -print 0:处理带有空格,,\,制表符和换行符的怪异文件名时,避免令人讨厌的惊喜。 -print0主目录与xargs -0结合使用可有效处理奇怪的文件名。
  • -maxdepth 1:最多在命令行参数下下降一个目录级别,即避免递归。
  • -exec rm -f {} +或者-exec ls {} +:在尽可能多的文件上运行rm或者ls命令。

选项#2:循环使用shell程序,以避免arg列表过长的错误

语法如下,它非常慢,可能根本无法工作:

for f in *; do command "$i"; done     
 
## delete all pdf files ##
for f in *.pdf; do /bin/rm -rf "$f"; done
 
############################################################################
### Delete all *.mp4 and *.avi files using pure Bash solution using arrays
### Based on http://mywiki.wooledge.org/BashFAQ/095 
############################################################################
files=($HOME/Downloads/*.avi $HOME/Downloads/*.mp4)
for ((i=0; i<${#files[*]}; i+=100)); do
   /bin/rm -vf "${files[@]:i:100}" 
done

命令摘要,以避免在shell中限制

## deals with weird filenames too ##
find /dir/to/search/ -name "file-pattern-search" -exec command {} + 
 
## find and xargs based solution ##
find /dir/to/search/ -name "file-pattern-search" -print0 | xargs -0 command
 
## For gnu parallel fans ##
find /dir/to/search/ -name 'file-pattern-search' -print0 | parallel -X -0 command
 
## older and not recommended solution; but kept here for the historical reasons only ##
for i in *; do command "$i"; done