Есть ли способ получить find
выполнение функции, которую я определяю в оболочке? Например:
dosomething () {
echo "doing something with $1"
}
find . -exec dosomething {} \;
Результат этого:
find: dosomething: No such file or directory
Есть ли способ получить find
, -exec
чтобы увидеть dosomething
?
$0
.find . -exec bash -c 'dosomething "$0"' {} \;
его, он будет обрабатывать пробелы (и другие странные символы) в именах файлов ...export -f
Будет работать только в некоторых версиях Баша. Это не posix, не кроссплатфорн, с ним/bin/sh
будет ошибкаисточник
while read
цикл for;for item in $(find . ); do some_function "${item}"; done
Ответ Яка выше великолепен, но в нем есть несколько ловушек, которые легко преодолеть:
Это использует нуль как разделитель вместо перевода строки, так что имена файлов с переводом строки будут работать. Он также использует
-r
флаг, который отключает обратную косую черту, без обратной косой черты в именах файлов не будет работать. Он также очищается,IFS
так что потенциальные конечные пробелы в именах не удаляются.источник
/bin/bash
но не будет работать в/bin/sh
. Какая жалость.Добавьте кавычки,
{}
как показано ниже:Это исправляет любую ошибку из-за специальных символов, возвращаемых
find
, например, файлами с круглыми скобками в имени.источник
{}
. Это сломается для имени файла, содержащего двойные кавычки.touch '"; rm -rf .; echo "I deleted all you files, haha
, К сожалению.-exec bash -c 'echo $0' '{}' \;
обратите внимание, что при использованииbash -c
$ 0 является первым аргументом, а не именем скрипта.Обработка результатов навалом
Для повышения эффективности, многие люди используют
xargs
для обработки результатов навалом, но это очень опасно. Из-за этого был введен альтернативный метод,find
который выполняет массовые результаты.Обратите внимание, что этот метод может идти с некоторыми оговорками, такими как, например, требование в POSIX
find
- иметь{}
в конце команды.find
передаст много результатов в качестве аргументов для одного вызова,bash
иfor
-loop перебирает эти аргументы, выполняя функциюdosomething
для каждого из них.Приведенное выше решение начинает аргументы в
$1
, поэтому есть_
(который представляет$0
).Обработка результатов по одному
Таким же образом, я думаю, что принятый верхний ответ должен быть исправлен, чтобы
Это не только более разумно, потому что аргументы всегда должны начинаться
$1
, но и использование$0
может привести к неожиданному поведению, если возвращаемое имя файлаfind
имеет особое значение для оболочки.источник
Пусть скрипт вызовет сам себя, передавая каждый найденный элемент в качестве аргумента:
Когда вы запускаете скрипт самостоятельно, он находит то, что вы ищете, и вызывает себя, передавая каждый результат поиска в качестве аргумента. Когда скрипт запускается с аргументом, он выполняет команды для аргумента и затем завершается.
источник
find: ‘myscript.sh’: No such file or directory
если начать какbash myscript.sh
...Для тех из вас, кто ищет функцию bash, которая будет выполнять данную команду для всех файлов в текущем каталоге, я скомпилировал один из приведенных выше ответов:
Обратите внимание, что он разрывается с именами файлов, содержащими пробелы (см. Ниже).
В качестве примера возьмем эту функцию:
Скажем, я хотел изменить все экземпляры hello to world во всех файлах в текущем каталоге. Я бы сделал:
Чтобы быть в безопасности с любыми символами в именах файлов, используйте:
(но вам нужен,
find
который обрабатывает,-print0
например, GNUfind
).источник
Я нахожу самый простой способ, как следует, повторяя две команды в одном
источник
Для справки, я избегаю этого сценария, используя:
Получите вывод команды find в текущем файле сценария и выполните итерацию по выводу, как вам нужно. Я согласен с принятым ответом, но я не хочу показывать функцию за пределами моего файла сценария.
источник
Невозможно выполнить функцию таким способом.
Чтобы преодолеть это, вы можете поместить свою функцию в скрипт оболочки и вызывать ее из
find
Теперь используйте его в find как:
источник
dosomething $1
=>dosomething "$1"
и начните свой файл правильно сfind . -exec bash dosomething.sh {} \;
Поместите функцию в отдельный файл и
find
выполните ее.Функции оболочки являются внутренними по отношению к оболочке, в которой они определены;
find
никогда не сможет их увидеть.источник
Чтобы предоставить дополнения и пояснения к некоторым другим ответам, если вы используете опцию массового ввода для
exec
илиexecdir
(-exec command {} +
) и хотите получить все позиционные аргументы, вам необходимо рассмотреть обработку$0
сbash -c
. Более конкретно, рассмотрим приведенную ниже команду, которая использует,bash -c
как предложено выше, и просто выводит пути к файлам, заканчивающиеся на «.wav», из каждого найденного каталога:Руководство по bash гласит:
Здесь
'check $@'
- командная строка, и_ {}
аргументы после командной строки. Обратите внимание, что$@
это специальный позиционный параметр в bash, который распространяется на все позиционные параметры, начиная с 1 . Также обратите внимание, что с помощью-c
опции первый аргумент назначается позиционному параметру$0
. Это означает, что если вы попытаетесь получить доступ ко всем позиционным параметрам с помощью$@
, вы получите только параметры, начиная с$1
и выше. Именно поэтому в ответе Доминика есть_
фиктивный аргумент для заполнения параметра$0
, поэтому все нужные нам аргументы будут доступны позже, если мы используем$@
расширение параметра, например, или цикл for, как в этом ответе.Конечно, аналогично принятому ответу,
bash -c 'shell_function $0 $@'
также будет работать явное прохождение$0
, но опять же, вы должны иметь в виду, что$@
это не сработает, как ожидалось.источник
Не напрямую, нет. Find выполняется в отдельном процессе, а не в вашей оболочке.
Создайте сценарий оболочки, который выполняет ту же работу, что и ваша функция, и найдите его
-exec
.источник
Я бы не использовал
-exec
вообще. Почему бы не использоватьxargs
?источник