найти -exec функцию оболочки в Linux?
Есть ли способ получить find
для выполнения функции, которую я определяю в оболочке? Например:
dosomething () {
echo "doing something with $1"
}
find . -exec dosomething {} \;
Результат:
find: dosomething: No such file or directory
Есть ли способ получить find
-exec
, чтобы увидеть dosomething
?
Ответы
Ответ 1
Поскольку только оболочка знает, как запускать функции оболочки, вам нужно запустить оболочку для запуска функции. Вы также должны пометить свою функцию для экспорта с помощью export -f
, иначе подоболочка не наследует их:
export -f dosomething
find . -exec bash -c 'dosomething "$0"' {} \;
Ответ 2
find . | while read file; do dosomething "$file"; done
Ответ 3
Добавьте кавычки в {}
, как показано ниже:
export -f dosomething
find . -exec bash -c 'dosomething "{}"' \;
Это исправляет любую ошибку из-за специальных символов, возвращаемых find
,
например файлы с круглыми скобками в их имени.
Ответ 4
Ответ на Jak выше велик, но есть пара ошибок, которые легко преодолеть:
find . -print0 | while IFS= read -r -d '' file; do dosomething "$file"; done
В качестве ограничителя вместо null, используется значение null, поэтому имена файлов с линией перевода будут работать. Он также использует флаг -r
, который отключает экранирование обратного слэша, без его обратных косов в именах файлов не будет работать. Он также очищает IFS
, так что потенциальные конечные пробелы в именах не отбрасываются.
Ответ 5
Иметь вызов script, передавая каждый найденный элемент в качестве аргумента:
#!/bin/bash
if [ ! $1 == "" ] ; then
echo "doing something with $1"
exit 0
fi
find . -exec $0 {} \;
exit 0
Когда вы запускаете script самостоятельно, он находит то, что вы ищете, и называет себя передачей каждого результата поиска в качестве аргумента. Когда script запускается с аргументом, он выполняет команды в аргументе и затем выходит.
Ответ 6
Обработка результатов навалом
Для повышения эффективности многие люди используют xargs
для обработки результатов навалом, но это очень опасно. Из-за этого был альтернативный метод, введенный в find
, который выполняет результаты в массе.
Обратите внимание, что этот метод может содержать некоторые предостережения, например, требование в POSIX- find
, чтобы иметь {}
в конце команды.
export -f dosomething
find . -exec bash -c 'for f; do dosomething "$f"; done' _ {} +
find
будет передавать множество результатов в качестве аргументов для одного вызова bash
, а for
-loop выполняет итерацию через эти аргументы, выполняя функцию dosomething
для каждого из них.
Вышеприведенное решение запускает аргументы в $1
, поэтому существует _
(который представляет $0
).
Обработка результатов по одному
Таким же образом, я считаю, что принятый верхний ответ должен быть исправлен как
export -f dosomething
find . -exec bash -c 'dosomething "$1"' _ {} \;
Это не только более разумно, потому что аргументы всегда должны начинаться с $1
, но также с помощью $0
может привести к неожиданному поведению, если имя файла, возвращаемое find
, имеет специальное значение для оболочки.
Ответ 7
Для тех из вас, кто ищет функцию bash, которая выполнит заданную команду для всех файлов в текущем каталоге, я скомпилировал один из приведенных выше ответов:
toall(){
find . -type f | while read file; do "$1" "$file"; done
}
Обратите внимание, что он разбивается на имена файлов, содержащие пробелы (см. ниже).
В качестве примера возьмем эту функцию:
world(){
sed -i 's_hello_world_g' "$1"
}
Скажем, я хотел изменить все экземпляры приветствия миру во всех файлах в текущем каталоге. Я бы сделал:
toall world
Чтобы быть в безопасности с любыми символами в именах файлов, используйте:
toall(){
find . -type f -print0 | while IFS= read -r -d '' file; do "$1" "$file"; done
}
(но вам нужен find
, который обрабатывает -print0
, например, GNU find
).
Ответ 8
Невозможно выполнить эту функцию таким образом.
Чтобы преодолеть это, вы можете поместить свою функцию в оболочку script и вызвать ее из find
# dosomething.sh
dosomething () {
echo "doing something with $1"
}
dosomething $1
Теперь используйте его в find как:
find . -exec dosomething.sh {} \;
Ответ 9
Поместите функцию в отдельный файл и получите find
, чтобы выполнить это.
Функции оболочки являются внутренними для оболочки, в которой они определены; find
никогда не сможет их увидеть.
Ответ 10
Я нахожу самый простой способ, как следует, повторяя две команды в одиночном do
func_one () {
echo "first thing with $1"
}
func_two () {
echo "second thing with $1"
}
find . -type f | while read file; do func_one $file; func_two $file; done
Ответ 11
Не прямо, нет. Поиск выполняется в отдельном процессе, а не в вашей оболочке.
Создайте оболочку script, которая выполняет ту же работу, что и ваша функция, и найдите -exec
.
Ответ 12
Для справки, я избегаю этого сценария, используя:
for i in $(find $dir -type f -name "$name" -exec ls {} \;); do
_script_function_call $i;
done;
Получите вывод find в текущем файле скрипта и выполните итерацию по выводу, как вам захочется. Я согласен с принятым ответом, но я не хочу показывать функцию за пределами моего файла сценария.
Ответ 13
Я бы вообще не использовал -exec
. Почему бы не использовать xargs
?
find . -name <script/command you're searching for> | xargs bash -c