rm,cp,mv命令的参数列表太长错误

在UNIX中的目录下有几百个PDF文件。 PDF的名称非常长(约60个字符)。

当我尝试使用以下命令一起删除所有PDF:

rm -f *.pdf 

我得到以下错误:

 /bin/rm: cannot execute [Argument list too long] 

这个错误的解决scheme是什么? 这个错误是否也发生在mvcp命令中呢? 如果是,如何解决这些命令?

发生这种情况的原因是因为bash实际上将星号扩展为每个匹配的文件,产生了一个非常长的命令行。

尝试这个:

 find . -name "*.pdf" -print0 | xargs -0 rm 

警告:这是一个recursionsearch,也会在子目录中find(和删除)文件。 只有在确定不需要确认的情况下,才可以在-r命令上使用rm命令。

如果你在Linux上,你可以执行以下命令来使这个命令不recursion:

 find . -maxdepth 1 -name "*.pdf" -print0 | xargs -0 rm 

另一个select是使用find的-delete标志:

 find . -name "*.pdf" -delete 

TL;博士

这是命令行参数大小的内核限制。 改用for循环。

问题的根源

这是一个系统问题,与execveARG_MAX常量有关。 有很多关于这方面的文档(请参阅man execve , debian的wiki )。

基本上,扩展会产生超过ARG_MAX限制的命令 (使用其参数)。 在内核2.6.23 ,限制设置为128 kB 。 这个常数已经增加了,你可以通过执行以下操作来获得它的值:

 getconf ARG_MAX # 2097152 # on 3.5.0-40-generic 

在BashFAQ / 095上推荐使用for循环,除了RAM /内存空间外,没有限制:

 for f in *.pdf; do rm "$f"; done 

这也是一个便携式的方法,因为glob在shell之间有很强的一致性( POSIX规范的一部分 )。

如果你坚持,你可以使用find但实际上不使用xargs,因为它在读取非NUL分隔的input时是危险的(破坏,可利用等)

 find . -name '*.pdf' -exec rm {} + 

参考

  • 我得到“参数列表太长”。 我如何处理一个大块的列表? @ wooledge
  • execve(2) – Linux手册页 (searchARG_MAX);
  • 错误:参数列表太长了 @ Debian的wiki;
  • 为什么在传递引用的参数时会得到“/ bin / sh:参数列表太长”? @超级用户

find有一个-delete行动:

 find . -maxdepth 1 -name '*.pdf' -delete 

另一个答案是强制xargs批量处理命令。 例如,要一次delete文件100 ,请进入该目录并运行以下命令:

echo *.pdf | xargs -n 100 rm

或者你可以尝试:

 find . -name '*.pdf' -exec rm -f {} \; 

你可以使用一个bash数组:

 files=(*.pdf) for((I=0;I<${#files[*]};I+=1000)); do rm -f ${files[@]:I:1000}; done 

这样它会每批次擦除1000个文件。

你可以试试这个:

 for f in *.pdf do rm $f done 

编辑:ThiefMaster评论build议我不要向年轻的shell的杰西披露这样的危险的做法,所以我会添加一个更“安全”的版本(为了保存的东西,当有人有一个“-rf。.. pdf”文件)

 echo "# Whooooo" > /tmp/dummy.sh for f in '*.pdf' do echo "rm -i $f" >> /tmp/dummy.sh done 

运行完上面的代码之后,只需打开/tmp/dummy.sh文件即可。 编辑器,并检查每一行危险的文件名,如果发现评论他们。

然后复制你的工作目录中的dummy.sh脚本并运行它。

这一切都是出于安全原因。

你可以使用这个表扬

 find -name "*.pdf" -delete 

我在将表单源目录复制到目标时面临同样的问题

源目录有文件~3个lakcs

我用选项-r使用cp,它对我有用

cp -r abc / def /

它会将所有文件从abc复制到def,而不会给参数列表发出警告太久

rm命令限制了可以同时删除的文件。

你可以使用多次rm命令来删除它们,这取决于你的文件模式,比如:

 rm -f A*.pdf rm -f B*.pdf rm -f C*.pdf ... rm -f *.pdf 

您也可以通过查找命令删除它们:

 find . -name "*.pdf" -exec rm {} \; 

如果它们是空格或特殊字符的文件名,请使用:

 find -maxdepth 1 -name '*.pdf' -exec rm "{}" \; 

这个句子用扩展名pdf(-name'* .pdf')search当前目录(-maxdepth 1)中的所有文件,然后删除每个文件(-exec rm“{}”)。

expression式{}replace文件的名称,并且“{}”将文件名设置为string,包括空格或特殊字符。

我遇到了这个问题几次。 许多解决scheme将针对每个需要删除的单个文件运行rm命令。 这是非常低效的:

 find . -name "*.pdf" -print0 | xargs -0 rm -rf 

我写了一个python脚本来删除基于文件名前4个字符的文件:

 import os filedir = '/tmp/' #The directory you wish to run rm on filelist = (os.listdir(filedir)) #gets listing of all files in the specified dir newlist = [] #Makes a blank list named newlist for i in filelist: if str((i)[:4]) not in newlist: #This makes sure that the elements are unique for newlist newlist.append((i)[:4]) #This takes only the first 4 charcters of the folder/filename and appends it to newlist for i in newlist: if 'tmp' in i: #If statment to look for tmp in the filename/dirname print ('Running command rm -rf '+str(filedir)+str(i)+'* : File Count: '+str(len(os.listdir(filedir)))) #Prints the command to be run and a total file count os.system('rm -rf '+str(filedir)+str(i)+'*') #Actual shell command print ('DONE') 

这对我来说工作得很好。 我能够在大约15分钟内清除文件夹中的超过200万个临时文件。 我从一点点的代码中评论了tar,所以任何一个只有很less或没有Python知识的人都可以操纵这个代码。

还有一个:

 cd /path/to/pdf printf "%s\0" *.[Pp][Dd][Ff] | xargs -0 rm 

我只知道一个办法。 这个想法是将你拥有的pdf文件列表导出到一个文件中。 然后将该文件分成几个部分。 然后删除每个部分中列出的PDF文件。

 ls | grep .pdf > list.txt wc -l list.txt 

wc -l是计算list.txt包含的行数。 当你知道它有多长时间的时候,你可以决定把它分成一半,四分之一或者其他东西。 使用split -l命令例如,将它分为600行。

 split -l 600 list.txt 

这将创build一个名为xaa,xab,xac等文件取决于你如何拆分它。 现在要将这些文件中的每个列表“导入”命令rm,使用:

 rm $(<xaa) rm $(<xab) rm $(<xac) 

对不起,我的英语不好。

我发现,对于非常大的文件列表(> 1e6),这些答案太慢了。 这是一个在python中使用并行处理的解决scheme。 我知道,我知道,这不是Linux …但这里没有其他工作。

(这节省了我的时间)

 # delete files import os as os import glob import multiprocessing as mp directory = r'your/directory' os.chdir(directory) files_names = [i for i in glob.glob('*.{}'.format('pdf'))] # report errors from pool def callback_error(result): print('error', result) # delete file using system command def delete_files(file_name): os.system('rm -rf ' + file_name) pool = mp.Pool(12) # or use pool = mp.Pool(mp.cpu_count()) if __name__ == '__main__': for file_name in files_names: print(file_name) pool.apply_async(delete_files,[file_name], error_callback=callback_error) 

试试这个也如果你想删除30/90天以上(+)或者30/90( – )天以下的文件/文件夹,那么你可以使用下面的ex命令

例如:在90天之后90天之内排除文件/文件夹删除之后,这意味着91,92 …. 100天

 find <path> -type f -mtime +90 -exec rm -rf {} \; 

例如:只有最近30天的文件,你想删除然后使用下面的命令( – )

 find <path> -type f -mtime -30 -exec rm -rf {} \; 

如果你想giz文件超过2天的文件

 find <path> -type f -mtime +2 -exec gzip {} \; 

如果你想只看到过去一个月的文件/文件夹。 例如:

 find <path> -type f -mtime -30 -exec ls -lrt {} \; 

30天以上才能列出文件/文件夹例如:

 find <path> -type f -mtime +30 -exec ls -lrt {} \; find /opt/app/logs -type f -mtime +30 -exec ls -lrt {} \; 

使用GNU并行( sudo apt install parallel )是非常容易的

它运行multithreading命令,其中“{}”是传递的参数

例如

ls /tmp/myfiles* | parallel 'rm {}'

假设input目录名称是input,并输出输出目录名称。 那么你可以使用简单的循环来复制所有

 for f in input/* do cp $f output done 

我遇到了同样的问题,这个文件夹里面充满了日益增长的临时图像,这个命令帮助我清除了文件夹

 find . -name "*.png" -mtime +50 -exec rm {} \; 

与其他命令的不同之处在于mtime参数只会取得大于X天的文件(在本例中为50天)

多次使用,减less每一次执行的date范围,我能够删除所有不必要的文件

如果你有类似的grep问题,最简单的解决方法是步进一个目录并做一个recursionsearch。

所以,而不是

 grep "something" * 

您可以使用:

 cd .. grep "something" -R search_in_this_dir/ 

注意它会recursion地search“search_in_this_dir”目录的子文件夹。

比使用xargs更安全的版本,也不recursion: ls -p | grep -v '/$' | grep '\.pdf$' | while read file; do rm "$file"; done ls -p | grep -v '/$' | grep '\.pdf$' | while read file; do rm "$file"; done

在这里过滤我们的目录是不必要的,因为'rm'不会删除它,为简单起见,它可以被删除,但是为什么要运行一些肯定会返回错误的东西呢?

下面的选项对这个问题似乎很简单。 我从其他线程得到这个信息,但它帮助了我。

 for file in /usr/op/data/Software/temp/application/openpages-storage/*; do cp "$file" /opt/sw/op-storage/ done 

只要运行上面的一个命令就可以完成任务。