2015-03-10 1 views
1

Я пытаюсь выполнить питон скрипт на все текстовые файлы в папке:Python - для фи в sys.argv [1]: список аргументов слишком долго

for fi in sys.argv[1:]: 

И я получаю следующее сообщение об ошибке

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

Так я называю эту функцию Python заключается в следующем:

python functionName.py *.txt 

папка имеет около 9000 файлов. Есть ли способ запустить эту функцию, не разбирая мои данные в других папках и т. Д.? Разделение файлов было бы не очень практичным, потому что в будущем мне придется выполнять эту функцию в еще большем количестве файлов ... Спасибо

EDIT: На основании выбранного правильного ответа и комментариев ответчика (Charles Duffy) что работает для меня заключается в следующем:

printf '%s\0' *.txt | xargs -0 python ./functionName.py 

, потому что у меня нет действительной хижины ..

+3

Это не вызвано самим python, а использованием os. Вот ссылка на эту тему: http://stackoverflow.com/questions/5533704/python-sys-argv-limitations Но в любом случае это не лучшая практика, попробуйте что-то вроде ледяного. – Igle

+0

(В другом месте - модули Python * должны иметь расширения '.py'. * Исполняемые файлы *, написанные на Python, не должны содержать расширение - исполняемые файлы определяют команды, и вы не запускаете' ls.elf' - - но вместо этого следует использовать shebang для указания своего интерпретатора ('#!/usr/bin/env python' или такого) и быть отмеченным исполняемым (' chmod + x functionName'). –

+0

... если вы используете setuptools, ll автоматически создает и устанавливает исполняемые файлы обертки для вас, которые вызывают функции, которые вы хотите запустить, эти оболочки, как правило, являются исполняемыми командами без расширений. –

ответ

5

Это я S проблема на уровне ОС (ограничение на длину командной строки), и обычно решается с помощью ОС-уровня (или, по крайней мере, снаружи вашего-Python-процесс) решение:

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

... или ...

printf '%s\0' *.txt | xargs -0 ./your-python-program 

Обратите внимание, что это работает your-python-program один раз в партии найденных файлов, где размер пакета зависит от количества имен, которые могут поместиться в ARG_MAX; см. отличный ответ Маркуса Мюллера, если это непригодно.

+0

Когда я пытаюсь сделать первый, я получаю следующую ошибку: sudo find. -maxdepth 1 -type f -name '* .txt' -exec ./removeHtmlAndUnuuencode.py '{}' + найти: ./functionName.py: запрещен отказ найти: ./functionName.py: запрещен отказ – adrCoder

+0

Когда я попробуйте вторую. Я получаю следующую ошибку: xargs: ./functionName.py: Permission denied -bash: printf: write error: Broken pipe – adrCoder

+0

«Разрешение отказано» означает, что он говорит; вам нужно «chmod + x./functionName.py', и убедитесь, что он начинается с shebang (' #!/usr/bin/env python', или '#!/usr/bin/env python2', в зависимости от ситуации для вашей ОС). Или '-exec python ./your-python-program {} +', чтобы вообще не понадобиться shebang. –

1

не делать это таким образом. Передайте маску в свой скрипт python (например, назовите ее python functionName.py "*.txt") и разверните ее с помощью glob (https://docs.python.org/2/library/glob.html).

+0

Конечно, один _can_ сделать это, но это не обычное/стандартное поведение в UNIX любыми средствами. 'ls' берет список имен файлов, а не подстановочный знак (например); то же самое для 'tar', и ... ну, почти все другие стандартные инструменты. –

+0

Также удачи передают файл с глобусом в его имени, который соответствует другим файлам, без использования вашей программы и для других файлов. –

+0

ls не будет для него и в этом случае. – iced

1

Я думаю об использовании glob модуля. С помощью этого модуля вы вызываете программу как:

python functionName.py "*.txt" 

тогда оболочка не будет расширяться *.txt в имена файлов. Вы программа Python получит *.txt в списке и Аргументы вы можете передать его в glob.glob():

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

Traceback (последний звонок последний): Файл «functionName.py», строка 64, в для fi в glob.glob (sys.argv [1:]): Файл «/ Система/Библиотека/Рамки /Python.framework/Versions/2.7/lib/python2.7/glob.py ", строка 27, в glob список возвратов (iglob (путь)) Файл" /System/Library/Frameworks/Python.framework/Versions/ 2.7/lib/python2.7/glob.py ", строка 38, в iglob if not has_magic (путь): Файл" /System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/ glob.py ", строка 95, in has_magic return magic_check.search (s) не является None ТипError: ожидаемая строка или бафф – adrCoder

+0

^Это ошибка, которую я получаю, когда пытаюсь сделать то, что вы говоря – adrCoder

+0

Да. Теперь я отредактировал его с предположением, что будет использоваться только одна файловая маска. –

2

Нет, это ограничение ядра для длины (в байтах) в командной строке.

Как правило, вы можете определить, что предел, делая

getconf ARG_MAX 

, который, по крайней мере для меня, дает 2097152 (байт), что означает около 2 Мб.

Я рекомендую использовать 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 - 
+0

'printf '% s \ n' * .txt' более безопасен, чем' ls * .txt' - см. Http://mywiki.wooledge.org/ParsingLs –

+0

Даже лучше, чем это, будет 'printf '% s \ 0 '* .txt' и интерпретируя поток с разделителями NUL, который генерирует - в противном случае имена файлов с буквальными символами новой строки (да, они законны в UNIX) выкинут. –

+0

('readlines()' является неправильным инструментом для работы по той же причине). –