Я использую Solaris 10, и я протестировал следующее с помощью ksh (88), bash (3.00) и zsh (4.2.1).
Следующий код не дает никакого результата:
function foo {
echo "Hello World"
}
find somedir -exec foo \;
Поиск действительно соответствует нескольким файлам (как показано заменой -exec ...
на -print
), и функция отлично работает при вызове вне find
вызова.
Вот что man find
говорится на странице -exec
:
-exec команда Истина, если выполненная команда возвращает нулевое значение в качестве состояния выхода. Конец Команда должна быть акцентирована сбежавшим точка с запятой (;). Аргумент команды {} заменяется текущим путем. Если последний аргумент для -exec это {} и вы укажите + вместо точки с запятой (;), команда вызывается меньше раз, с {} заменяется группами путей. Если любой вызов команды возвращает ненулевое значение в качестве статуса выхода, найти возвращает ненулевой статус выхода.
Я мог бы, вероятно, уйти, делая что-то вроде этого:
for f in $(find somedir); do
foo
done
Но я боюсь иметь дело с проблемами разделителя полей.
Можно ли вызвать функцию оболочки (определенную в том же сценарии, давайте не будем беспокоиться о проблемах с областями видимости) из find ... -exec ...
вызова?
Я попробовал это с обоими /usr/bin/find
и /bin/find
и получил тот же результат.
export -f foo
PATH
. В качестве альтернативы используйтеsh -c '...'
и оба определите И запустите функцию в...
бите. Это может помочь понять различия между функциями и сценариями .Ответы:
A
function
является локальным по отношению к оболочке, поэтому вам нужноfind -exec
будет создать оболочку и определить эту функцию в этой оболочке, прежде чем использовать ее. Что-то типа:bash
позволяет экспортировать функции через окружениеexport -f
, поэтому вы можете сделать (в bash):ksh88
долженtypeset -fx
экспортировать функцию (не через окружение), но она может использоваться только сценариями, выполняемыми she-bang lessksh
, но не с помощьюksh -c
.Другой вариант заключается в следующем:
То есть используйте
typeset -f
для выгрузки определенияfoo
функции внутри встроенного скрипта. Обратите внимание, что еслиfoo
используются другие функции, вам также нужно будет их сбросить.источник
ksh
илиbash
в-exec
команде? Я понимаю первое, но не второе происшествие.bash -c 'some-code' a b c
,$0
isa
,$1
isb
..., поэтому, если вы хотите$@
быть,a, b, c
вам нужно вставить что-то раньше. Поскольку$0
также используется при отображении сообщений об ошибках, рекомендуется использовать имя оболочки или что-то, что имеет смысл в этом контексте.Это не всегда применимо, но когда это так, это простое решение. Установите
globstar
опцию (set -o globstar
в ksh93,shopt -s globstar
в bash ≥4; по умолчанию она включена в zsh). Затем используйте**/
для рекурсивного сопоставления текущего каталога и его подкаталогов.Например, вместо
find . -name '*.txt' -exec somecommand {} \;
, вы можете запуститьВместо этого
find . -type d -exec somecommand {} \;
вы можете запуститьВместо этого
find . -newer somefile -exec somecommand {} \;
вы можете запуститьЕсли у
**/
вас не работает (потому что ваша оболочка его не имеет или вам нужнаfind
опция, у которой нет аналога оболочки), определите функцию вfind -exec
аргументе .источник
globstar
вариант для версии ksh (ksh88
), которую я использую.dtksh
существовала версия ksh93 (ksh93 с некоторыми расширениями X11), но старая версия и, возможно, часть дополнительного пакета, где CDE не является обязательным.find
что оно исключает точечные файлы и не спускается в точечные каталоги, а также сортирует список файлов (оба из которых могут быть адресами в zsh через классификаторы глобинга). Также**/*
в отличие от./**/*
, имена файлов могут начинаться с-
.Используйте \ 0 в качестве разделителя и считывайте имена файлов в текущий процесс из порожденной команды, например так:
Что тут происходит:
read -d ''
читает до следующего байта \ 0, поэтому вам не нужно беспокоиться о странных символах в именах файлов.-print0
использует \ 0 для завершения каждого сгенерированного имени файла вместо \ n.cmd2 < <(cmd1)
аналогично тому,cmd1 | cmd2
что cmd2 запускается в основной оболочке, а не в подоболочке./dev/null
того, чтобы он случайно не читал из канала.$filename
в кавычках, поэтому оболочка не пытается разделить имя файла, содержащее пробел.Теперь
read -d
и<(...)
в Zsh, Баш и КШ 93u, но я не уверен , о ранее КШ версии.источник
если вы хотите, чтобы дочерний процесс, порожденный из вашего скрипта, использовал предопределенную функцию оболочки, вам нужно экспортировать его с
export -f <function>
ПРИМЕЧАНИЕ:
export -f
это специфично для bashпоскольку только оболочка может выполнять функции оболочки :
РЕДАКТИРОВАТЬ: по сути, ваш сценарий должен выглядеть следующим образом:
источник
export -f
является синтаксической ошибкой вksh
, и выводит определение функции на экран вzsh
. В целомksh
,zsh
иbash
это не решает проблему.find / -exec /bin/bash -c 'function' \;
bash
. Спасибо!{}
в код оболочки! Это означает, что имя файла интерпретируется как шелл-код, что очень опасно