Почему зацикливание на выводе find - плохая практика?

Питон!

Существует ряд библиотек для управления файлами PDF, включая неподдерживаемый pyPdf и его форк PyPDF2 . Вы можете обрабатывать файл постранично, извлекать текст и копировать страницы, текст которых подходит.

Я выполнил следующее, используя Python3.6 и PyPDF2 == 1.26.0:

#!/usr/bin/env python3
import re
import sys

from PyPDF2 import PdfFileWriter, PdfFileReader

pdf_in = PdfFileReader(sys.stdin.buffer)
pdf_out = PdfFileWriter()
for p in [pdf_in.getPage(i) for i in range(0, pdf_in.getNumPages())]:
    text = p.extractText()
    if not re.search(r'for\s+office\s+use\s+only', text, re.I):
        pdf_out.addPage(p)
pdf_out.write(sys.stdout.buffer)

Помните, что текст может отображаться в документе не так, как вы этого хотите. В документе PDF строки, слова или даже символы могут отображаться не по порядку. Документ может состоять не из потока текста, а из частей, появляющихся в определенных координатах.

Даже если текст находится в правильном порядке, что обычно имеет место, текст, занимающий несколько страниц, будет иметь нижний колонтитул и верхний колонтитул посередине. Текст, занимающий несколько строк, может иметь лишние пробелы вокруг разрывов строк. Даже текст в одних и тех же строках может иметь несколько пробелов между словами из-за выравнивания текста (поэтому я использовал \ s + , а не простой пробел в регулярном выражении выше).

Инструменты, извлекающие текст из PDF, пытаются реконструировать страницу как текст, но не всегда работают безупречно.Если pyPdf плохо работает с вашими документами, вы можете попробовать другие библиотеки для извлечения текста; см. этот и этот поток для некоторых примеров.

193
16.10.2017, 01:09
7 ответов

Проблема

for f in $(find .)

объединяет две несовместимые вещи.

find печатает список путей к файлам, разделенных символами новой строки. Оператор split + glob, который вызывается, когда вы оставляете этот $ (find.) без кавычек в контексте этого списка, разбивает его на символы $ IFS (по умолчанию включает новую строку, но также пробел и табуляция (и NUL в zsh )) и выполняет подстановку для каждого результирующего слова (кроме zsh ) (и даже раскрытие фигурных скобок в ksh93 (даже если фигурная скобка раскрывается опция отключена в старых версиях) или производных pdksh!).

Даже если вы это сделаете:

IFS='
' # split on newline only
set -o noglob # disable glob (also disables brace expansion
              # done upon other expansions in ksh)
for f in $(find .) # invoke split+glob

Это все равно неверно, поскольку символ новой строки так же допустим, как и любой другой в пути к файлу. Вывод find -print просто не поддается постобработке (за исключением использования некоторого запутанного трюка , как показано здесь ).

Это также означает, что оболочке необходимо полностью сохранить вывод find , а затем разделить + glob его (что подразумевает сохранение этого вывода во второй раз в памяти) перед тем, как начать цикл по файлам.

Обратите внимание, что находят.| xargs cmd имеет аналогичные проблемы (там пробелы, новая строка, одинарные кавычки, двойные кавычки и обратная косая черта (а с некоторыми xarg реализациями байты, не являющиеся частью допустимых символов) являются проблемой)

Подробнее правильные альтернативы

Единственный способ использовать цикл for на выходе find - это использовать zsh , который поддерживает IFS = $ ' \ 0 ' и:

IFS=$'\0'
for f in $(find . -print0)

(замените -print0 на -exec printf'% s \ 0 '{} + для найдите реализации, которые не поддерживают нестандартный (но довольно распространенный в настоящее время) -print0 ).

Здесь правильный и переносимый способ - использовать -exec :

find . -exec something with {} \;

Или, если что-то может принимать более одного аргумента:

find . -exec something with {} +

Если вам действительно нужен этот список файлов, которые будут обрабатываться оболочкой:

find . -exec sh -c '
  for file do
    something < "$file"
  done' find-sh {} +

(будьте осторожны, она может запускать более одного sh ).

В некоторых системах вы можете использовать:

find . -print0 | xargs -r0 something with

, хотя это имеет небольшое преимущество перед стандартным синтаксисом и означает, что что-то stdin является либо каналом, либо / dev / null .

Одна из причин, по которой вы можете захотеть использовать это, может заключаться в использовании опции -P в GNU xargs для параллельной обработки. Проблема stdin также может быть решена с помощью GNU xargs с параметром -a с оболочками, поддерживающими замену процесса: например

xargs -r0n 20 -P 4 -a <(find . -print0) something

, чтобы запустить до 4 одновременных вызова чего-то , каждый из которых принимает 20 аргументов файла.

С помощью zsh или bash , другой способ перебрать вывод find -print0 - это:

while IFS= read -rd '' file <&3; do
  something "$file" 3<&-
done 3< <(find . -print0)

read -d '' читает записи с разделителями NUL вместо записей с разделителями новой строки.

bash-4.4 и более поздние версии также могут хранить файлы, возвращенные командой find -print0 , в массиве с:

readarray -td '' files < <(find . -print0)

эквивалентом zsh (который имеет преимущество сохранения статус выхода find ):

files=(${(0)"$(find . -print0)"})

С помощью zsh вы можете преобразовать большинство выражений find в комбинацию рекурсивной подстановки с квалификаторами glob. Например, перебирая find. -name '* .txt' -type f -mtime -1 будет:

for file (./**/*.txt(ND.m-1)) cmd $file

или

for file (**/*.txt(ND.m-1)) cmd -- $file

(остерегайтесь необходимости - как с ** / * , пути к файлам не начинаются с ./ , поэтому могут начинаться, например, с - ).

ksh93 и bash в конечном итоге добавили поддержку ** / (хотя и не более продвинутые формы рекурсивного подстановки), но все же не квалификаторы glob, которые используют ** там очень ограничено. Также помните, что bash до 4.3 следует за символическими ссылками при спуске по дереву каталогов.

Как и в случае перебора $ (find.) , это также означает сохранение всего списка файлов в памяти 1 .Это может быть желательно в некоторых случаях, когда вы не хотите, чтобы ваши действия с файлами влияли на поиск файлов (например, когда вы добавляете больше файлов, которые в конечном итоге могут быть найдены сами) .

Другие соображения надежности / безопасности

Условия состязания

Теперь, если мы говорим о надежности,мы должны упомянуть условия гонки между временем, когда find / zsh находит файл и проверяет его соответствие критериям, а также время его использования ( TOCTOU race ]).

Даже при спуске по дереву каталогов необходимо следить за тем, чтобы не следовать символическим ссылкам и делать это без гонки TOCTOU. find (как минимум GNU find ) делает это, открывая каталоги с помощью openat () с правильными флагами O_NOFOLLOW (где поддерживается) и сохраняя дескриптор файла открытым для каждого каталога, zsh / bash / ksh этого не делают. Таким образом, если злоумышленник сможет заменить каталог символической ссылкой в ​​нужное время, вы можете в конечном итоге перейти не в тот каталог.

Даже если find действительно спускается по каталогу правильно, с помощью -exec cmd {} \; и тем более с -exec cmd {} + , после выполнения cmd , например, как cmd ./foo/bar или cmd ./foo/bar ./foo/bar/baz, к моменту времени cmd использует ./ foo / bar , атрибуты bar могут больше не соответствовать критериям, указанным в find , но даже хуже того, ./ foo мог быть заменен символической ссылкой на другое место (а окно гонки стало намного больше с помощью -exec {} + где find ожидает достаточного количества файлов для вызова cmd ).

Некоторые реализации find имеют (пока нестандартный) предикат -execdir для решения второй проблемы.

С помощью:

find . -execdir cmd -- {} \;

найдите chdir () s в родительском каталоге файла перед запуском cmd . Вместо вызова cmd - ./foo/bar он вызывает cmd - ./bar ( cmd - bar с некоторыми реализациями, отсюда - ), поэтому проблема с изменением ./ foo на символическую ссылку устранена. Это делает использование таких команд, как rm , более безопасным (он все равно может удалить другой файл, но не файл в другом каталоге), но не команд, которые могут изменять файлы, если они не были разработаны так, чтобы не следовать символическим ссылкам .

-execdir cmd - {} + иногда также работает, но с несколькими реализациями, включая некоторые версии GNU find , он эквивалентен -execdir cmd - {} \; .

-execdir также позволяет обойти некоторые проблемы, связанные со слишком глубокими деревьями каталогов.

В:

find . -exec cmd {} \;

размер пути, заданного для cmd , будет расти вместе с глубиной каталога, в котором находится файл. Если этот размер станет больше, чем PATH_MAX (что-то например, 4k в Linux), то любой системный вызов, выполняемый cmd по этому пути, завершится ошибкой ENAMETOOLONG .

С -execdir только имя файла (возможно, с префиксом ./ ) передается в cmd .Сами имена файлов в большинстве файловых систем имеют гораздо более низкий предел ( NAME_MAX ), чем PATH_MAX , поэтому ошибка ENAMETOOLONG встречается с меньшей вероятностью.

Байты против символов

Кроме того, при рассмотрении вопросов безопасности, связанных с find и, в более общем плане, с обработкой имен файлов в целом часто упускается из виду тот факт, что в большинстве Unix-подобных систем имена файлов представляют собой последовательности байтов. (любое байтовое значение, кроме 0 в пути к файлу, и в большинстве систем (основанных на ASCII, мы пока проигнорируем редкие, основанные на EBCDIC) 0x2f - разделитель пути).

Приложения должны решить, хотят ли они рассматривать эти байты как текст. И они обычно это делают, но обычно перевод байтов в символы выполняется на основе локали пользователя, на основе среды.

Это означает, что данное имя файла может иметь различное текстовое представление в зависимости от локали. Например, последовательность байтов 63 f4 74 e9 2e 74 78 74 будет côté.txt для приложения, интерпретирующего это имя файла в локали с набором символов ISO-8859- 1 и cєtщ.txt в локали, где вместо этого используется кодировка IS0-8859-5.

Хуже. В языковом стандарте, где используется кодировка UTF-8 (норма в настоящее время), 63 f4 74 e9 2e 74 78 74 просто невозможно сопоставить с символами!

find - одно из таких приложений, которое рассматривает имена файлов как текст для своих предикатов -name / -path (и других, например -iname ] или -regex с некоторыми реализациями).

Это означает, что, например, с несколькими реализациями find (включая GNU find ).

find . -name '*.txt'

не сможет найти наш 63 f4 74 e9 2e 74 78 74 файл выше при вызове в локали UTF-8 как * (который соответствует 0 или более символов , а не байты) не может соответствовать этим несимволам.

LC_ALL = C find ... может обойти проблему, поскольку локаль C подразумевает один байт на символ и (обычно) гарантирует, что все значения байтов отображаются на символ (хотя, возможно, неопределенные для некоторых значений байтов) .

Теперь, когда дело доходит до перебора этих имен файлов из оболочки, этот байт против символа также может стать проблемой. В этом отношении мы обычно видим 4 основных типа оболочек:

  1. Те, которые еще не поддерживают многобайтовую обработку, такие как тире . Для них байт соответствует символу. Например, в UTF-8 côté - это 4 символа, но 6 байтов. В языковом стандарте, где кодировка UTF-8, в

      найти. -имя '????' -exec тире -c '
    имя = $ {1 ## * /}; echo "$ {# name}" 'sh {} \; 
     

find успешно найдет файлы, имя которых состоит из 4 символов в кодировке UTF-8, но тире ] будет указывать длину от 4 до 24.

  1. yash : наоборот. Он работает только с символами . Все вводимые данные внутренне переводятся в символы. Это делает оболочку наиболее согласованной, но это также означает, что она не может справиться с произвольными последовательностями байтов (теми, которые не преобразуются в допустимые символы). Даже в языковом стандарте C он не справляется со значениями байтов выше 0x7f.

      находят.-exec yash -c 'echo "$ 1"' sh {} \; 
     

в языковом стандарте UTF-8 не будет работать с нашим ISO-8859-1 côté.txt из более ранней версии. например.

  1. Такие, как bash или zsh , где постепенно добавлялась поддержка многобайтовой информации. Они вернутся к рассмотрению байтов, которые нельзя сопоставить с символами, как если бы они были символами. У них все еще есть несколько ошибок здесь и там, особенно с менее распространенными многобайтовыми кодировками, такими как GBK или BIG5-HKSCS (они довольно неприятны, поскольку многие из их многобайтовых символов содержат байты в диапазоне 0-127 (например, символы ASCII) ).

  2. Такие, как sh FreeBSD (по крайней мере, 11) или mksh -o utf8-mode , которые поддерживают многобайтовый формат, но только для UTF-8.

Примечания

1 Для полноты мы могли бы упомянуть хакерский способ в zsh перебирать файлы с помощью рекурсивного подстановки без сохранения всего списка в памяти:

process() {
  something with $REPLY
  false
}
: **/*(ND.m-1+process)

+ cmd ] - квалификатор glob, который вызывает cmd (обычно функция) с текущим путем к файлу в $ REPLY . Функция возвращает истину или ложь, чтобы решить, следует ли выбрать файл (а также может изменить $ REPLY или вернуть несколько файлов в массиве $ reply ). Здесь мы выполняем обработку в этой функции и возвращаем false, чтобы файл не был выбран.

117
20.08.2021, 11:54

Почему цикл вывода find - плохая практика?

Простой ответ:

Поскольку имена файлов могут содержать любой символ.

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


Новые строки часто используются (неправильно) для разделения имен файлов, потому что необычно включать символы новой строки в имена файлов.

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

Если вы можете писать программное обеспечение двумя разными способами, и один из них правильно обрабатывает крайние случаи (необычные входные данные), а другой легче читать, вы можете возразить, что есть компромисс. (Я бы не стал. Я предпочитаю правильный код.)

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


Давайте будем более конкретными: в системе UNIX или Linux имена файлов могут содержать любой символ, кроме / (который используется в качестве разделителя компонентов пути), и они не могут содержать нулевой байт.

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


Поскольку GNU find включает первичный элемент -print0 , который будет использовать нулевой байт для ограничения имен файлов, которые он печатает, GNU find можно безопасно используется с GNU xargs и его флагом -0 (и флагом -r ) для обработки вывода find :

find ... -print0 | xargs -r0 ...

Однако , нет веской причины для использования этой формы, потому что:

  1. Он добавляет зависимость от GNU findutils, которой нет необходимости, а
  2. find - это разработан , чтобы иметь возможность запускать команды для найденных файлов.

Кроме того, GNU xargs требует -0 и -r , тогда как FreeBSD xargs требует только -0 ] (и не имеет опции -r ), а некоторые xargs вообще не поддерживают -0 . Так что лучше всего придерживаться функций POSIX find (см. Следующий раздел) и пропускать xargs .

Что касается пункта 2 - способность find запускать команды в найденных файлах - я думаю, что Майк Лукидес сказал это лучше всего:

find занимается оценкой выражений - не поиск файлов. Да, find определенно находит файлы; но на самом деле это всего лишь побочный эффект.

- Unix Power Tools


В POSIX указано использование find

Как правильно запускать одну или несколько команд для каждого из результатов find ?

Чтобы запустите одну команду для каждого найденного файла, используйте:

find dirname ... -exec somecommand {} \;

Чтобы запустить несколько команд в последовательности для каждого найденного файла, где вторая команда должна запускаться только в случае успеха первой команды, используйте:

find dirname ... -exec somecommand {} \; -exec someothercommand {} \;

Чтобы запустить одну команду на несколько файлов одновременно:

find dirname ... -exec somecommand {} +

найти в сочетании с sh

Если вам нужно использовать в команде функции оболочки , такие как перенаправление вывода или удаление расширения из filename или что-то подобное, вы можете использовать конструкцию sh -c . Вы должны знать несколько вещей об этом:

  • Никогда не вставляйте {} непосредственно в код sh . Это позволяет выполнять произвольный код из злонамеренно созданных имен файлов. Кроме того, на самом деле в POSIX даже не указано, что он вообще будет работать. (См. Следующий пункт.)

  • Не используйте {} несколько раз,или используйте его как часть более длинного спора. Это не переносится. Например, не делайте этого:

    find ... -exec cp {} somedir / {}. Bak \;

    Процитируем спецификации POSIX для find :

    Если строка имя_программы или аргумент содержит два символа «{}», но не только два символа «{}», то определяется реализацией, найдет ли заменяет эти два символа или использует строку без изменений.

    ... Если присутствует более одного аргумента, содержащего два символа "{}", поведение не определено.

  • Аргументы, следующие за командной строкой оболочки, переданной в параметр -c , устанавливаются в позиционные параметры оболочки, начиная с $ 0 . Не начиная с $ 1 .

    По этой причине рекомендуется включить фиктивное значение $ 0 , например find-sh , которое будет использоваться для сообщения об ошибках из порожденной оболочки. Кроме того, это позволяет использовать такие конструкции, как «$ @» при передаче нескольких файлов в оболочку, тогда как отсутствие значения для $ 0 будет означать, что первый переданный файл будет установлен в $ 0 и поэтому не включается в «$ @» .


Чтобы запустить одну команду оболочки для каждого файла, используйте:

find dirname ... -exec sh -c 'somecommandwith "$1"' find-sh {} \;

Однако обычно это дает лучшую производительность для обработки файлов в цикле оболочки, так что вы не создаете оболочку для каждого найденного файла:

find dirname ... -exec sh -c 'for f do somecommandwith "$f"; done' find-sh {} +

(Обратите внимание, что для f do эквивалентно для f в «$ @»; do и обрабатывает каждый из позиционных параметров по очереди - другими словами, он использует каждый из файлов найдено с помощью find , независимо от каких-либо специальных символов в их именах.)


Дополнительные примеры правильного использования find :

(Примечание: не стесняйтесь расширять этот список.)

198
20.08.2021, 11:54

Этот ответ предназначен для очень больших наборов результатов и в основном касается производительности, например, при получении списка файлов по медленной сети. Для небольшого количества файлов (скажем, несколько сотен или, может быть, даже 1000 на локальном диске) большая часть этого спорна.

Параллелизм и использование памяти

Помимо других приведенных ответов, связанных с проблемами разделения и т. Д., Есть еще одна проблема с

for file in `find . -type f -name ...`; do smth with ${file}; done

Часть внутри обратных кавычек должна быть сначала полностью оценена, прежде чем разделяться на перенос строки . Это означает, что если вы получаете огромное количество файлов, он может либо подавиться любыми ограничениями размера, установленными в различных компонентах; у вас может закончиться память, если нет ограничений; и в любом случае вам придется подождать, пока find не выведет весь список, а затем проанализирует на , прежде чем запускать свой первый smth .

Предпочтительный способ unix - работать с конвейерами, которые по своей сути работают параллельно и которые также не нуждаются в произвольно огромных буферах в целом.Это означает: вы бы предпочли, чтобы find выполнялся параллельно с вашим smth , и сохранял только текущее имя файла в ОЗУ, пока он передает его smth .

Одно, по крайней мере частично, неплохое решение для этого - вышеупомянутый find -exec smth . Это устраняет необходимость хранить все имена файлов в памяти и прекрасно работает параллельно. К сожалению, он также запускает один smth процесс для каждого файла. Если smth может работать только с одним файлом, значит, так и должно быть.

Если это вообще возможно, оптимальным решением было бы find -print0 | smth , при этом smth может обрабатывать имена файлов на своем STDIN. Тогда у вас есть только один smth процесс, независимо от количества файлов, и вам нужно буферизовать только небольшое количество байтов (независимо от того, какая внутренняя буферизация канала) между двумя процессами. Конечно, это нереально, если smth является стандартной командой Unix / POSIX, но это может быть подход, если вы пишете ее самостоятельно.

Если это невозможно, то find -print0 | xargs -0 smth , вероятно, одно из лучших решений.Как @ dave_thompson_085 упомянул в комментариях, xargs действительно разделяет аргументы между несколькими запусками smth , когда достигаются системные ограничения (по умолчанию в диапазоне 128 КБ или любой другой предел exec в системе), и имеет параметры, влияющие на то, сколько файлов передается одному вызову smth , таким образом находя баланс между количеством smth процессы и начальная задержка.

РЕДАКТИРОВАТЬ: убрано понятие «лучший» - сложно сказать, появится ли что-то лучшее. ;)

13
20.08.2021, 11:54

Одна из причин в том, что пробельные символы мешают работе, заставляя файл 'foo bar' оцениваться как 'foo' и 'bar'.

$ ls -l
-rw-rw-r-- 1 ec2-user ec2-user 0 Nov  7 18:24 foo bar
$ for file in `find . -type f` ; do echo filename $file ; done
filename ./foo
filename bar
$

Работает нормально, если вместо этого используется -exec

$ find . -type f -exec echo filename {} \;
filename ./foo bar
$ find . -type f -exec stat {} \;
  File: ‘./foo bar’
  Size: 0               Blocks: 0          IO Block: 4096   regular empty file
Device: ca01h/51713d    Inode: 9109        Links: 1
Access: (0664/-rw-rw-r--)  Uid: (  500/ec2-user)   Gid: (  500/ec2-user)
Access: 2016-11-07 18:24:42.027554752 +0000
Modify: 2016-11-07 18:24:42.027554752 +0000
Change: 2016-11-07 18:24:42.027554752 +0000
 Birth: -
$
4
20.08.2021, 11:54

Зацикливание на выводе find - неплохая практика. Плохая практика (в этой и всех ситуациях) - это при условии, что ваш ввод является особенным формат вместо , зная, что (тестирование и подтверждение), это конкретный формат.

tldr / cbf: найти | параллельный материал

0
20.08.2021, 11:54

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

Во-вторых, если вам не нужна конкретная функция find , имейте в виду, что ваша оболочка, скорее всего, уже может самостоятельно расширять рекурсивный шаблон глобуса, и, что особенно важно, он будет расширяться до правильного массива.

Пример Bash:

shopt -s nullglob globstar
for i in **
do
    echo «"$i"»
done

То же самое в Fish:

for i in **
    echo «$i»
end

Если вам действительно нужны функции find , убедитесь, что разбиение выполняется только по NUL (например, find -print0 | xargs -r0 идиома).

Fish может повторять вывод с разделителями NUL. Так что это на самом деле неплохо :

find -print0 | while read -z i
    echo «$i»
end

В качестве последнего небольшого подводного камня, во многих оболочках (не в Fish, конечно) зацикливание вывода команд сделает тело цикла подоболочкой (это означает, что вы не можете установить переменную каким-либо образом, которая будет видна после завершения цикла), что никогда не является тем, что вам нужно.

2
20.08.2021, 11:54

Зацикливание вывода find является часто плохой практикой, особенно в сценариях общего назначения, когда вы мало что знаете об обстоятельствах, это используется.

В моей повседневной работеУ меня часто достаточно знаний о файлах ниже одного подкаталога, чтобы исключить возможность попадания в токсичное имя файла. И я никогда не использую имена файлов с пробелами, символами новой строки, табуляцией и т.п. в своих именах самостоятельно. Во-первых, это плохая идея, напрашивающаяся на проблемы.

Например, у меня есть скрипт для сжатия изображений с моей камеры, который является общим и никогда не изменится. Их путь не содержит пробелов и имен файлов. (IMG00001.JPG )Если я получу новую камеру, мне нужно будет изменить сценарий.

Для специальных команд, выданных и забытых, это не проблема. Для однопользовательских машин, если вы не делитесь своим кодом, это тоже не должно быть проблемой.

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

Учитывая поиск Gnu в Linux -, у него есть 4 параметра для выполнения команд над файлами, например

find. -type f -name... -exec do-smth-with {} ";"

и кроме -exec есть -execdir, -ok и -okdir для аналогичных целей. Версии ~каталога -выполняют действие из каталога, файл встречается, в отличие от вашего текущего каталога, который рекомендуется. Версии ok ~-требуют подтверждения для выполнения команды.

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

Завершение команды с помощью ";" можно заменить знаком плюс без кавычек, если вызываемая команда изящно обрабатывает большой набор файлов в качестве параметров.

После выполнения вы даже можете передать дополнительные параметры для поиска, например:

find -name "*.html" -execdir wc {} + -ls 

чтобы привести простой пример.

Я не могу свидетельствовать о других реализациях find.

-4
20.08.2021, 11:54

Теги

Похожие вопросы