Я хочу вызвать use find
для некоторых имен файлов.
find $(do_something to find filenames) -print0 | xargs -r0 ls -ld
Это прерывает работу, если $(do_something to find filenames)
ничего не возвращает: команда find начинает выполнять рекурсивный поиск.
Есть ли способ заставить find ничего не делать, если в качестве аргумента не указано явное имя файла/каталога?
решение1
С zsh
, я бы сделал:
files=($(do_something to find filenames))
(($#files)) && find $files ...
С tcsh
:
set files=(`do_something to find filenames`)
if ($#files) find $files:q ...
С bash
, mksh
или ksh93
,
set -f; files=($(do_something to find filenames))
((${#files[@]})) && find "${files[@]}" ...
POSIXly:
set -f; set -- $(do_something to find filenames)
[ "$#" -gt 0 ] && find "$@" ...
(в bash и других оболочках POSIX $(...)
разделяет ( $IFS
по умолчанию по пробелу, табуляции и новой строке), но также выполняет подстановку результирующих слов, что, как я ожидаю, вам здесь не понадобится, отсюда и set -f
. В других оболочках ((t)csh, zsh, fish, rc, es...) такой проблемы нет).
решение2
Как насчет того, чтобы сделать это:
paths=$(do_something to find filenames)
if [ "$paths" ]; then
find "$paths" ...
fi
Это работает независимо от find
реализации.
Обратите внимание, что find "$paths"
при наличии более одного имени пути возникают проблемы. Если имена путей не содержат пробелов, вы можете использовать: find $paths
, в противном случае рабочей альтернативой является эта функция:
dofind() {
set -f
set -- $(do_something to find filenames)
if [ $# -gt 0 ]; then
find "$@" ...
fi
set +f
}
Он отключает подстановку файлов и затем использует set --
для установки вектора аргументов оболочки. Это работает с любой оболочкой POSIX.
решение3
Вы можете указать find
дополнительный, несуществующий каталог, с которого будет начинаться:
find " " $(do_something to find filenames) -print0 | xargs -r0 ls -ld
Чтобы сделать это аккуратнее, удалите find
вывод ошибок:
find " " $(do_something to find filenames) -print0 2>/dev/null | xargs -r0 ls -ld
(но тогда вы не заметите, если возникнет еще одна ошибка...).
Когда do_something to find filenames
выводит имена файлов, find
будет жаловаться " "
, но все равно обработает остальную часть командной строки. Когда имена файлов не выводятся, find
снова будет жаловаться, " "
но не добавит свой default .
.
решение4
В zsh
(и большинстве не-Bourne-производных оболочек), когда a (иливсев зависимости от оболочки)шарне расширяется, команда прерывается.
$(do_something to find filenames)
не является глобом, но вы можете сделать его таковым, добавив квалификатор глобуса в zsh
:
find $(do_something to find filenames)(#q) -print0...
Выше, это (#q)
(пустой квалификатор glob, так что ничего не делает в противном случае) добавляется к последнему слову, полученному в результате разделения вывода do_something to find filenames
, поэтому команда будет прервана, если эта команда не даст (или даст пустой) вывод, но также если это последнее слово (и только это последнее слово) не разрешается в существующий путь. Вы можете применить это к каждому слову, полученному в результате этого разделения (так что команда будет прервана, если любое из этих слов не разрешается в существующий файл) с помощью:
find ${^$(do_something to find filenames)}(#q) -print0...