Это не бесконечный цикл , это просто GNU find
сообщает, что echo
умерло из-за SIGPIPE (потому что другой конец конвейера на stdout был закрыто, когда голова
умерла).
-execdir
не указан в POSIX. И даже для -exec
в спецификации POSIX нет ничего, что говорило бы, что если команда прервана SIGPIPE, find
должен завершиться.
Таким образом, если бы в POSIX было указано -execdir
, gfind
, вероятно, он был бы более совместим с POSIX, чем ваш BSD find
(при условии, что ваш BSD find завершает работу после смерти дочернего элемента SIGPIPE, как следует из формулировки вашего вопроса, FreeBSD find
не входит в мои тесты и запускает echo
в цикле для каждого файла (например, для GNU find, не бесконечно)).
Вы можете сказать, что для наиболее распространенных случаев find
завершение после смерти ребенка от SIGPIPE было бы предпочтительнее, но команда -exec
uted могла бы умереть из-за SIGPIPE для других Причины, по которым канал на stdout закрыт, поэтому выход из find
для этого будет гранично приемлемым.
С помощью GNU find
вы можете указать find
завершить работу в случае сбоя команды с помощью:
find . ... \( -exec echo {} \; -o -quit \)
Относительно того, разрешена или запрещена реализация find
чтобы сообщить о детях, умирающих из-за сигнала на stderr, здесь (с использованием -execdir
) мы в любом случае выходим за рамки POSIX, но если -exec
использовалось вместо -execdir
, похоже, это может быть случай, когда gfind не соответствует.
Спецификация для find
гласит: «стандартная ошибка должна использоваться только для диагностических сообщений» , но также говорит там :
Поведение по умолчанию: Когда этот раздел указан как «Стандартная ошибка должна использоваться только для диагностических сообщений», это означает, что, если не указано иное, диагностические сообщения должны отправляться в стандартную ошибку только тогда, когда статус выхода указывает, что произошла ошибка и утилита используется, как описано в этом томе POSIX.1-2008.
Это означает, что, поскольку find
в этом случае не возвращается с ненулевым статусом выхода, он не должен выводить это сообщение на stderr.
Обратите внимание, что в этом тексте и GNU, и FreeBSD find
будут несовместимы в таких случаях, как:
$ find /dev/null -exec blah \;; echo "$?"
find: `blah': No such file or directory
0
, где оба сообщают об ошибке, не устанавливая для статуса выхода ненулевое значение. Вот почему я поднял вопрос в списке рассылки austin-group (парни, стоящие за POSIX) .
Обратите внимание, что если вы измените свою команду на:
(trap '' PIPE; find -L /etc -execdir echo {} \; | head)
echo
по-прежнему будет запускаться для каждого файла, все равно не удастся, но на этот раз сообщение об ошибке будет сообщаться echo
.
Теперь отображается filename
vs / etc / filename
vs ./ filename
.
Опять же, -execdir
не является стандартным параметром, поэтому нет текста, который говорит, кто прав, а кто виноват. -execdir
был введен BSD find
и позже скопирован GNU find
.
В GNU find
были внесены некоторые преднамеренные изменения (улучшения) по сравнению с ним. Например, он добавляет к именам файлов ./
в аргументах, передаваемых командам. Это означает, что находят. -execdir cmd {} \;
не имеет проблем с именами файлов, начинающимися, например, с -
.
Тот факт, что -L -execdir
не передает путь к файлу относительно родительского каталога, на самом деле является ошибкой , которая затрагивает версии 4.3.0–4.5.8 GNU найдите
. Это было исправлено в 4.5.9, но это находится в ветке разработки, и с тех пор не было новой стабильной версии (по состоянию на 22 декабря 2015 года, хотя она неизбежна ).
Дополнительная информация в списке рассылки findutils .
Если все, что вам нужно, это вывести базовое имя каждого файла в / etc
переносимо, вы можете просто сделать:
find -L /etc -exec basename {} \;
Или более эффективно:
find -L ///etc | awk -F / '/\/\// && NR>1 {print last}
{if (NF > 1) last = $NF
else last = last "\n" $NF}
END {if (NR) print last}'
, который можно упростить до
find -L /etc | awk -F / '{print $NF}'
, если вы можете гарантировать, что пути к файлам не содержат символов новой строки (хотя IIRC, некоторые версии OS / X имели такие файлы в / etc).
GNUly:
find -L /etc -printf '%f\n'
Относительно того, является ли:
find -exec echo {} \;
в ссылке , на которую вы ссылаетесь, POSIX или нет.
Нет, как вызов команды, это не POSIX. Сценарий , который будет иметь это, будет несовместим.
POSIX find
требует, чтобы был указан хотя бы один путь, но оставляет поведение неопределенным, если первый аргумент без параметра find
начинается с -
или является предикатом find
(например, !
или (
), поэтому поведение GNU find
соответствует , поэтому - реализации, которые сообщают об ошибке (или рассматривать первый аргумент как путь к файлу, даже если он представляет собой предикат поиска) или распылять красную краску себе в лицо, нет причин, по которым POSIXLY_CORRECT
повлияет на поведение find
там.
python36u
— альтернативная сборка, предоставленная IUS ; python36
— это пакет EPEL .
yum info python36 python36u
покажет вам разные репозитории для этих двух пакетов, и вполне вероятно, что IUS имеет немного более высокий дополнительный номер версии, чем пакет EPEL. И чтобы еще больше запутать вас, есть еще Redhat Software Collections ,которые обеспечивают rh-python36-python
.
В конечном итоге все сводится к обмену -последней версии и длительному циклу поддержки, я полагаю.