найти-exec функцию оболочки в Linux?
есть ли способ сделать find
для выполнения функции, которую я определяю в оболочке? Например:
dosomething () {
echo "doing something with "
}
find . -exec dosomething {} ;
результат:
find: dosomething: No such file or directory
есть ли способ сделать find
' s -exec
посмотреть dosomething
?
12 ответов:
export -f, иначе подобласть не унаследует их:
export -f dosomething find . -exec bash -c 'dosomething ""' {} \;
добавить кавычки в
{}
как показано ниже:export -f dosomething find . -exec bash -c 'dosomething "{}"' \;
это исправляет любую ошибку из-за специальных символов, возвращаемых
find
, например, файлы с круглыми скобками в их имени.
Джека, но имеет несколько подводных камней, которые легко преодолеть:
find . -print0 | while IFS= read -r -d '' file; do dosomething "$file"; done
Это использует null в качестве разделителя вместо linefeed, так что имена файлов с linefeed будет работать. Он также использует
-r
флаг, который отключает обратную косую черту экранирования, без него обратные косые черты в именах файлов не будет работать. Он также очищаетIFS
Так что потенциальные конечные пробелы в именах не отбрасываются.
вызовите сам скрипт, передавая каждый найденный элемент в качестве аргумента:
#!/bin/bash if [ ! == "" ] ; then echo "doing something with " exit 0 fi find . -exec {} \; exit 0
когда вы запускаете скрипт сам по себе, он находит то, что вы ищете, и вызывает себя, передавая каждый результат поиска в качестве аргумента. Когда скрипт запускается с аргументом, он выполняет команды для аргумента, а затем завершает работу.
обработка результатов навалом
для повышения эффективности, многие люди используют
xargs
обрабатывать результаты навалом, но это очень опасно. Из-за этого был введен альтернативный метод вfind
что выполняет результаты навалом.обратите внимание, что этот метод может прийти с некоторыми оговорками, как например требование в POSIX -
find
иметь{}
в конце команды.export -f dosomething find . -exec bash -c 'for f; do dosomething "$f"; done' _ {} +
find
пройдет много результатов аргументы для одного вызоваbash
иfor
-цикл перебирает эти аргументы, выполняя функциюdosomething
на каждом из них.приведенное выше решение запускает аргументы в
, который является, почему есть
_
(что составляет).
обработка результатов один за другим
таким же образом, я думаю, что принятый верхний ответ должен быть исправлен, чтобы быть
export -f dosomething find . -exec bash -c 'dosomething ""' _ {} \;
это не только более здраво, потому что аргументы всегда должны начинаться с
, но и
может привести к неожиданному поведению, если имя, возвращенное
find
имеет особое значение для оболочки.
для тех из вас, кто ищет функцию bash, которая будет выполнять данную команду для всех файлов в текущем каталоге, я скомпилировал один из приведенных выше ответов:
toall(){ find . -type f | while read file; do "" "$file"; done }
обратите внимание, что он ломается с именами файлов, содержащих пробелы (см. ниже).
в качестве примера возьмем эту функцию:
world(){ sed -i 's_hello_world_g' "" }
скажем, я хотел изменить все экземпляры hello to world во всех файлах в текущем каталоге. Я бы сделал:
toall world
будет безопасный с любыми символами в именах файлов, использовать:
toall(){ find . -type f -print0 | while IFS= read -r -d '' file; do "" "$file"; done }
(но вам нужно
find
обработки-print0
например, GNUfind
).
невозможно выполнить a функции этак.
чтобы преодолеть это, вы можете поместить свою функцию в сценарий оболочки и вызвать ее из
find
# dosomething.sh dosomething () { echo "doing something with " } dosomething
Теперь используйте его в find as:
find . -exec dosomething.sh {} \;
поставить функцию в отдельный файл и сделать
find
выполнить, что.функции оболочки являются внутренними для оболочки, в которой они определены;
find
никогда не сможет увидеть их.
Я нахожу самый простой способ, как показано ниже, повторяя две команды в одном do
func_one () { echo "first thing with " } func_two () { echo "second thing with " } find . -type f | while read file; do func_one $file; func_two $file; done