Argument list too long error for rm, cp, mv commands
我在UNIX的目录下有几百个PDF。 PDF的名称非常长(大约60个字符)。
当我尝试使用以下命令一起删除所有PDF时:
1 | rm -f *.pdf |
我收到以下错误:
1 | /bin/rm: cannot execute [Argument list too long] |
这个错误的解决方案是什么?
是否还会对
发生这种情况的原因是因为bash实际上将星号扩展到每个匹配的文件,从而产生一个非常长的命令行。
试试这个:
1 | find . -name"*.pdf" -print0 | xargs -0 rm |
警告:这是一个递归搜索,也会在子目录中找到(和删除)文件。只有在您确定不需要确认时,才能将
您可以执行以下操作以使命令非递归:
1 | find . -maxdepth 1 -name"*.pdf" -print0 | xargs -0 rm |
另一种选择是使用find的
1 | find . -name"*.pdf" -delete |
TL;博士
这是对命令行参数大小的内核限制。请改用
问题的根源
这是一个与
基本上,扩展产生的命令(其参数)超过
在内核
1 2 | getconf ARG_MAX # 2097152 # on 3.5.0-40-generic |
解决方案:使用
在BashFAQ / 095上推荐使用
1 | for f in *.pdf; do rm"$f"; done |
这也是一种可移植的方法,因为glob在shell中具有强大且一致的行为(POSIX规范的一部分)。
注意:正如一些评论所指出的那样,这确实更慢但更易于维护,因为它可以适应更复杂的情况,例如:人们想要做的不仅仅是一个动作。
解决方案:使用
如果你坚持,你可以使用
1 | find . -maxdepth 1 -name '*.pdf' -delete |
使用
参考
- 我得到的"参数列表太长了"。如何以块的形式处理大型列表? @wooledge
- execve(2) - Linux手册页(搜索ARG_MAX);
- 错误:参数列表太长@ Debian的维基;
- 传递引用的参数时,为什么我会得到"/ bin / sh:参数列表太长"? @SuperUser
1 | find . -maxdepth 1 -name '*.pdf' -delete |
另一个答案是强制
或者您可以尝试:
1 | find . -name '*.pdf' -exec rm -f {} \; |
你可以试试这个:
1 2 3 4 | for f in *.pdf do rm $f done |
编辑:
ThiefMaster的评论建议我不要向年轻的shell的jedis透露这种危险的做法,所以我会添加一个更"安全"的版本(为了保存某些人有"-rf .pdf"文件的东西)
1 2 3 4 5 | echo"# Whooooo"> /tmp/dummy.sh for f in '*.pdf' do echo"rm -i $f">> /tmp/dummy.sh done |
运行上面的内容后,只需打开你的收藏夹中的/tmp/dummy.sh文件即可。编辑并检查每一行的危险文件名,如果找到则将其评论出来。
然后复制工作目录中的dummy.sh脚本并运行它。
所有这些都是出于安全考虑
如果您尝试一次删除大量文件(我今天删除了485,000+的目录),您可能会遇到此错误:
1 | /bin/rm: Argument list too long. |
问题是,当您键入类似
为了解决这个问题,很多人会使用find命令查找每个文件并将它们逐个传递给"rm"命令,如下所示:
1 | find . -type f -exec rm -v {} \; |
我的问题是我需要删除500,000个文件,这需要花费太长时间。
我偶然发现了一种更快的删除文件的方式 -"find"命令内置了一个"-delete"标志!这是我最终使用的内容:
1 | find . -type f -delete |
使用这种方法,我以大约2000个文件/秒的速度删除文件 - 快得多!
您还可以在删除文件名时显示这些文件名:
1 | find . -type f -print -delete |
...甚至显示将删除多少文件,然后计算删除它们所需的时间:
1 2 3 4 5 | root@devel# ls -1 | wc -l && time find . -type f -delete 100000 real 0m3.660s user 0m0.036s sys 0m0.552s |
你可以用这个推荐
1 | find -name"*.pdf" -delete |
你可以使用bash数组:
1 2 3 4 | files=(*.pdf) for((I=0;I<${#files[@]};I+=1000)); do rm -f"${files[@]:I:1000}" done |
这样,它将逐步擦除1000个文件。
rm命令具有可以同时删除的文件的限制。
您可以使用多次rm命令删除它们的一种可能性是基于您的文件模式,例如:
1 2 3 4 5 | rm -f A*.pdf rm -f B*.pdf rm -f C*.pdf ... rm -f *.pdf |
您也可以通过find命令删除它们:
1 | find . -name"*.pdf" -exec rm {} \; |
如果它们是带空格或特殊字符的文件名,请使用:
1 | find -maxdepth 1 -name '*.pdf' -exec rm"{}" \; |
这句话用扩展名pdf(-name'* .pdf')搜索当前目录(-maxdepth 1)中的所有文件,然后删除每一个文件(-exec rm"{}")。
表达式{}替换文件的名称,"{}"将文件名设置为字符串,包括空格或特殊字符。
我很惊讶这里没有
在将表单源目录复制到目标时,我遇到了同样的问题
源目录有文件~3 lakcs
我使用选项-r的cp,它对我有用
cp -r abc / def /
它会将所有文件从abc复制到def,而不会过长地发出Argument列表的警告
我碰到了几次这个问题。许多解决方案将为需要删除的每个文件运行
1 | find . -name"*.pdf" -print0 | xargs -0 rm -rf |
我最后编写了一个python脚本,根据文件名中的前4个字符删除文件:
1 2 3 4 5 6 7 8 9 10 11 12 | 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,所以任何具有最小到没有python知识的人都可以操作这段代码。
还有一个:
1 2 | cd /path/to/pdf printf"%s\0" *.[Pp][Dd][Ff] | xargs -0 rm |
因此我们可以安全地将它与shell globbing模式(如
我发现对于非常大的文件列表(> 1e6),这些答案太慢了。这是在python中使用并行处理的解决方案。我知道,我知道,这不是linux ......但这里没有其他工作。
(这节省了我几个小时)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | # 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) |
我只知道解决这个问题的方法。
我们的想法是将您拥有的pdf文件列表导出到文件中。然后将该文件拆分为几个部分。然后删除每个部分中列出的pdf文件。
1 2 | ls | grep .pdf > list.txt wc -l list.txt |
wc -l计算list.txt包含的行数。当你知道它有多长时间时,你可以决定将它分成两半,四分之一。使用split -l命令
例如,将它分成600行。
1 | split -l 600 list.txt |
这将创建一个名为xaa,xab,xac等文件,具体取决于你如何拆分它。
现在将这些文件中的每个列表"导入"命令rm,使用:
1 2 3 | rm $(<xaa) rm $(<xab) rm $(<xac) |
对不起,我的英语不好。
试试这个如果你想删除30/90天以上(+)或者30/90( - )天以下的文件/文件夹,那么你可以使用下面的ex命令
例如:在90天文件/文件夹删除后90天排除上述,这意味着91,92 .... 100天
1 | find <path> -type f -mtime +90 -exec rm -rf {} \; |
例如:对于您想要删除的最新30天文件,请使用以下命令( - )
1 | find <path> -type f -mtime -30 -exec rm -rf {} \; |
如果你想要文件超过2天giz文件
1 | find <path> -type f -mtime +2 -exec gzip {} \; |
如果你只想看过去一个月的文件/文件夹。
例如:
1 | find <path> -type f -mtime -30 -exec ls -lrt {} \; |
超过30天以上才会列出文件/文件夹
例如:
1 2 3 | find <path> -type f -mtime +30 -exec ls -lrt {} \; find /opt/app/logs -type f -mtime +30 -exec ls -lrt {} \; |
删除目录
1 2 3 | mkdir empty_dir # Create temp empty dir rsync -avh --delete --include '*.pdf' empty_dir/ /path/to/dir_with_pdf_files/ |
使用通配符通过
(可选步骤):DRY RUN。检查将删除的内容而不删除。 `
1 | rsync -avhn --delete --include '*.pdf' empty_dir/ /path/to/dir_with_pdf_files/ |
。
。
。
单击rsync提示和技巧以获取更多rsync黑客攻击
您可以创建临时文件夹,将要保留的所有文件和子文件夹移动到临时文件夹中,然后删除旧文件夹并将临时文件夹重命名为旧文件夹尝试此示例,直到您有信心实时执行:
1 2 3 4 5 6 7 8 | mkdir testit cd testit mkdir big_folder tmp_folder touch big_folder/file1.pdf touch big_folder/file2.pdf mv big_folder/file1,pdf tmp_folder/ rm -r big_folder mv tmp_folder big_folder |
如果您需要在删除大量文件时保持服务器或系统响应,则每个删除语句之间的
1 2 3 4 5 | find . -name"*.pdf" -print0 | while read -d $'\0' file do rm"$file" sleep 0.005 # Sleeps for 5ms, tweak as needed done |
当应用程序创建了数百万个无用的日志文件时,我遇到了类似的问题,这些文件填满了所有的inode。我使用"locate",将所有文件"定位"到一个文本文件中,然后逐个删除它们。花了一段时间,但做了这个工作!
如果你有类似grep的问题,最简单的解决方案是踩一个目录并进行递归搜索。
而不是
1 | grep"something" * |
您可以使用:
1 2 | cd .. grep"something" -R search_in_this_dir/ |
请注意,它也会递归搜索"search_in_this_dir"目录的子文件夹。
假设输入输入目录名称并输出输出目录名称。
然后你可以使用简单的循环来复制所有
1 2 3 4 | for f in input/* do cp $f output done |
我遇到了同样的问题,一个文件夹充满了日复一日的临时图像,这个命令帮助我清除了文件夹
1 | find . -name"*.png" -mtime +50 -exec rm {} \; |
与其他命令的区别在于mtime参数,该参数仅包含超过X天的文件(在示例中为50天)
多次使用,减少每天执行的日期范围,我能够删除所有不必要的文件
使用GNU parallel(
它运行多线程命令,其中'{}'是传递的参数
例如。
删除前100个文件:
rm -rf'ls |头-100'
比使用xargs更安全的版本,也不是递归的:
<5233>
在这里过滤我们的目录有点不必要,因为'rm'无论如何都不会删除它,并且为了简单起见它可以删除,但为什么运行肯定会返回错误的东西?
以下选项对于此问题似乎很简单。我从其他一些帖子得到了这个信息,但它帮助了我。
1 2 3 | for file in /usr/op/data/Software/temp/application/openpages-storage/*; do cp"$file" /opt/sw/op-storage/ done |
只需运行上面的一个命令就可以完成任务了。