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

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

rm -f *.pdf

我收到以下错误:

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

此错误的解决方案是什么?mv和cp命令是否也会出现此错误?如果是,如何解决这些命令?


当前回答

我发现对于非常大的文件列表(>1e6),这些答案太慢了。这里有一个在python中使用并行处理的解决方案。我知道,我知道,这不是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)

其他回答

删除目录/path/To/dir_with_pdf_files中的所有*.pdf/

mkdir empty_dir        # Create temp empty dir

rsync -avh --delete --include '*.pdf' empty_dir/ /path/to/dir_with_pdf_files/

如果您有数百万个文件,使用通配符通过rsync删除特定文件可能是最快的解决方案。它会解决你遇到的错误。


(可选步骤):干运行。检查将删除而不删除的内容`

rsync -avhn --delete --include '*.pdf' empty_dir/ /path/to/dir_with_pdf_files/

...

单击rsync提示和技巧以获取更多rsync黑客

我发现对于非常大的文件列表(>1e6),这些答案太慢了。这里有一个在python中使用并行处理的解决方案。我知道,我知道,这不是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)

要删除前100个文件:

rm-rf'ls|头部-100'

我用解决了

我在macOS上使用zsh

我只移动了数千个jpg文件。在一行命令中的mv内。

确保要移动的文件名中没有空格或特殊字符

for i in $(find ~/old -type f -name "*.jpg"); do mv $i ~/new; done

tl;博士

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

问题的根源

这是一个系统问题,与execve和ARG_MAX常量有关。有很多关于这方面的文档(参见man execve、debian的wiki、ARG_MAX详细信息)。

基本上,扩展生成的命令(及其参数)超过ARG_MAX限制。在内核2.6.23中,限制设置为128 kB。此常数已增加,您可以通过执行以下操作获取其值:

getconf ARG_MAX
# 2097152 # on 3.5.0-40-generic

解决方案:使用for循环

按照BashFAQ/095上的建议使用for循环,除了RAM/内存空间之外没有其他限制:

试运行以确定它将删除您期望的内容:

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

并执行它:

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

这也是一种可移植的方法,因为glob在shell之间具有强大且一致的行为(POSIX规范的一部分)。

注意:正如几条评论所指出的,这确实较慢,但更易于维护,因为它可以适应更复杂的场景,例如,一个人要做的不止一个动作。

解决方案:使用find

如果您坚持,您可以使用find,但实际上不要使用xargs,因为它“在读取非NUL分隔的输入时很危险(损坏、可利用等)”:

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

使用-maxdepth 1-delete而不是-exec rm{}+允许find在不使用外部进程的情况下简单地执行所需的系统调用,因此速度更快(多亏了@chepner注释)。

工具书类

我得到了“参数列表太长”。如何处理大块列表?@羊毛边的execve(2)-Linux手册页(搜索ARG_MAX);错误:参数列表太长@Debian的wiki;为什么在传递带引号的参数时会得到“/bin/sh:参数列表太长”?@超级用户