Vic*_*cky 584 unix linux command-line-arguments
我在UNIX的目录下有几百个PDF.PDF的名称非常长(大约60个字符).
当我尝试使用以下命令一起删除所有PDF时:
rm -f *.pdf
Run Code Online (Sandbox Code Playgroud)
我收到以下错误:
/bin/rm: cannot execute [Argument list too long]
Run Code Online (Sandbox Code Playgroud)
这个错误的解决方案是什么?这个错误是否也出现在命令mv
和cp
命令中?如果是,如何解决这些命令?
DPl*_*usV 807
发生这种情况的原因是因为bash实际上将星号扩展到每个匹配的文件,从而产生一个非常长的命令行.
试试这个:
find . -name "*.pdf" -print0 | xargs -0 rm
Run Code Online (Sandbox Code Playgroud)
警告:这是一个递归搜索,也会在子目录中找到(和删除)文件.-f
只有在您确定不需要确认时才能使用rm命令.
您可以执行以下操作以使命令非递归:
find . -maxdepth 1 -name "*.pdf" -print0 | xargs -0 rm
Run Code Online (Sandbox Code Playgroud)
另一种选择是使用find的-delete
标志:
find . -name "*.pdf" -delete
Run Code Online (Sandbox Code Playgroud)
Édo*_*pez 358
这是对命令行参数大小的内核限制.请改用for
循环.
这是一个系统问题,与之相关execve
并且ARG_MAX
不变.有很多关于这方面的文档(参见man execve,debian的wiki).
基本上,扩展产生超过限制的命令(及其参数)ARG_MAX
.在内核上2.6.23
,限制设置为128 kB
.这个常量已经增加,你可以通过执行以下方法获得它的值:
getconf ARG_MAX
# 2097152 # on 3.5.0-40-generic
Run Code Online (Sandbox Code Playgroud)
for
循环for
在BashFAQ/095上建议使用循环,除RAM /内存空间外没有限制:
for f in *.pdf; do rm "$f"; done
Run Code Online (Sandbox Code Playgroud)
这也是一种可移植的方法,因为glob在shell中具有强大且一致的行为(POSIX规范的一部分).
注意:正如一些评论所指出的那样,这确实更慢但更易于维护,因为它可以适应更复杂的场景,例如,人们想做的不仅仅是一个动作.
find
如果你坚持,你可以使用find
但实际上不使用xargs,因为它"在读取非NUL分隔的输入时是危险的(破坏,可利用等)":
find . -maxdepth 1 -name '*.pdf' -delete
Run Code Online (Sandbox Code Playgroud)
使用-maxdepth 1 ... -delete
而不是-exec rm {} +
允许find
简单地执行所需的系统调用而不使用外部进程,因此更快(感谢@chepner注释).
Thi*_*ter 178
find
有一个-delete
动作:
find . -maxdepth 1 -name '*.pdf' -delete
Run Code Online (Sandbox Code Playgroud)
por*_*ast 21
另一个答案是强制xargs
批量处理命令.例如,一次到delete
文件100
,cd
进入目录并运行:
echo *.pdf | xargs -n 100 rm
Dhi*_*mal 20
对于没有时间的人。 在终端上运行以下命令。
ulimit -S -s unlimited
Run Code Online (Sandbox Code Playgroud)
然后执行cp/mv/rm操作。
Jon*_*Lin 13
或者您可以尝试:
find . -name '*.pdf' -exec rm -f {} \;
Run Code Online (Sandbox Code Playgroud)
小智 11
如果您尝试一次删除大量文件(我今天删除了485,000+的目录),您可能会遇到此错误:
/bin/rm: Argument list too long.
Run Code Online (Sandbox Code Playgroud)
问题是当你键入类似的内容时rm -rf *
,*
会替换为每个匹配文件的列表,例如"rm -rf file1 file2 file3 file4"等等.有一个相对较小的内存缓冲区分配给存储这个参数列表,如果它被填满,shell将不会执行该程序.
为了解决这个问题,很多人会使用find命令查找每个文件并将它们逐个传递给"rm"命令,如下所示:
find . -type f -exec rm -v {} \;
Run Code Online (Sandbox Code Playgroud)
我的问题是我需要删除500,000个文件,这需要花费太长时间.
我偶然发现了一种更快的删除文件的方式 - "find"命令内置了一个"-delete"标志!这是我最终使用的内容:
find . -type f -delete
Run Code Online (Sandbox Code Playgroud)
使用这种方法,我以大约2000个文件/秒的速度删除文件 - 更快!
您还可以在删除文件名时显示这些文件名:
find . -type f -print -delete
Run Code Online (Sandbox Code Playgroud)
...甚至显示将删除多少文件,然后计算删除它们所需的时间:
root@devel# ls -1 | wc -l && time find . -type f -delete
100000
real 0m3.660s
user 0m0.036s
sys 0m0.552s
Run Code Online (Sandbox Code Playgroud)
Big*_*ike 10
你可以试试这个:
for f in *.pdf
do
rm $f
done
Run Code Online (Sandbox Code Playgroud)
编辑:ThiefMaster评论建议我不要向年轻的shell的jedis透露这种危险的做法,所以我会添加一个更"安全"的版本(为了保存事情,当有人有"-rf .pdf"文件时)
echo "# Whooooo" > /tmp/dummy.sh
for f in '*.pdf'
do
echo "rm -i $f" >> /tmp/dummy.sh
done
Run Code Online (Sandbox Code Playgroud)
运行上面的内容后,只需打开你的收藏夹中的/tmp/dummy.sh文件即可.编辑并检查每一行的危险文件名,如果找到则将其评论出来.
然后复制工作目录中的dummy.sh脚本并运行它.
所有这些都是出于安全考虑
小智 6
你可以使用bash数组:
files=(*.pdf)
for((I=0;I<${#files[@]};I+=1000)); do
rm -f "${files[@]:I:1000}"
done
Run Code Online (Sandbox Code Playgroud)
这样,它将逐步擦除1000个文件.
该RM命令有哪些可以删除文件同时的限制。
您可以根据文件模式多次使用rm命令删除它们,例如:
rm -f A*.pdf
rm -f B*.pdf
rm -f C*.pdf
...
rm -f *.pdf
Run Code Online (Sandbox Code Playgroud)
您还可以通过find命令删除它们:
find . -name "*.pdf" -exec rm {} \;
Run Code Online (Sandbox Code Playgroud)
如果它们是带有空格或特殊字符的文件名,请使用:
find -name "*.pdf" -delete
Run Code Online (Sandbox Code Playgroud)
仅适用于当前目录中的文件:
find -maxdepth 1 -name '*.pdf' -delete
Run Code Online (Sandbox Code Playgroud)
这句话搜索当前目录(-maxdepth 1)中所有扩展名为pdf(-name '*.pdf')的文件,然后删除。