найти-exec функцию оболочки в Linux?


есть ли способ сделать find для выполнения функции, которую я определяю в оболочке? Например:

dosomething () {
  echo "doing something with "
}
find . -exec dosomething {} ;

результат:

find: dosomething: No such file or directory

есть ли способ сделать find ' s -exec посмотреть dosomething?

12 143

12 ответов:

export -f, иначе подобласть не унаследует их:

export -f dosomething
find . -exec bash -c 'dosomething ""' {} \;
find . | while read file; do dosomething "$file"; done

добавить кавычки в {} как показано ниже:

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 например, GNU find).

невозможно выполнить 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

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

создайте сценарий оболочки, который выполняет ту же работу, что и ваша функция, и найдите can -exec что.

Я бы избегал использовать -exec в целом. Почему бы не использовать xargs?

find . -name <script/command you're searching for> | xargs bash -c