对于 sys.argv[1:] 中的 fi:参数列表太长

for fi in sys.argv[1:]: argument list too long

我正在尝试对文件夹中的所有文本文件执行 python 脚本:

for fi in sys.argv[1:]:

我收到以下错误

-bash: /usr/bin/python: Argument list too long

我调用此 Python 函数的方式如下:

python functionName.py *.txt

该文件夹有大约 9000 个文件。有什么方法可以 运行 这个功能,而不必将我的数据拆分到更多文件夹等中吗?拆分文件不是很实用,因为将来我将不得不在更多文件中执行该功能...谢谢

编辑:根据选择的正确回复和回复者 (Charles Duffy) 的评论,对我有用的是以下内容:

printf '%s[=14=]' *.txt | xargs -0 python ./functionName.py

因为我没有有效的 shebang..

不要这样做。将掩码传递给您的 python 脚本(例如将其称为 python functionName.py "*.txt")并使用 glob (https://docs.python.org/2/library/glob.html).

展开它

我考虑使用 glob 模块。使用此模块,您可以像这样调用您的程序:

python functionName.py "*.txt"

那么shell不会将*.txt扩展成文件名。您 Python 程序将在参数列表中收到 *.txt,您可以将其传递给 glob.glob():

for fi in glob.glob(sys.argv[1]):
    ...

没有。这是内核对命令行长度(以字节为单位)的限制。

通常,您可以通过

来确定该限制
getconf ARG_MAX

至少对我来说,产生 2097152(字节),这意味着大约 2MB。

我建议使用 python 自己处理文件夹,即让您的 python 程序能够处理目录而不是单个文件,或者从文件中读取文件名。

前者可以使用 os.walk(...) 轻松完成,而第二个选项(在我看来)更灵活。使用 argparse 模块为您的 python 程序提供易于使用的命令行语法,然后添加文件类型的参数(参见参考文档),python 将自动能够理解像 - 这样的特殊文件名,这意味着您可以代替

for fi in sys.argv[1:]

for fi in opts.file_to_read_filenames_from.read().split(chr(0))

这甚至可以让你做类似

的事情
find -iname '*.txt' -type f -print0|my_python_program.py -file-to-read-filenames-from - 

这是一个 OS 级别的问题(命令行长度限制),通常用 OS 级别解决(或者至少在你的外部 -Python-过程)解决方案:

find . -maxdepth 1 -type f -name '*.txt' -exec ./your-python-program '{}' +

...或者...

printf '%s[=11=]' *.txt | xargs -0 ./your-python-program

请注意,每找到一批文件运行一次 your-python-program,其中批大小取决于 ARG_MAX 中可以容纳的名称数量;如果这不合适,请参阅 Marcus Müller 的出色回答。