Вы можете хорошо использовать целевую -функцию значения переменной здесь:
build_x: version := latest
build_x:
@echo "Building version $(version)"
Не использовать find
, а использовать подстановку в оболочке zsh
:
$ printf '%s\n' **/foo/*(^/)
a/b/c/foo/z
a/b/foo/y
a/foo/x
foo/w
Здесь используется глобус **
, который «рекурсивно» сопоставляется с каталогами, чтобы соответствовать любому каталогу с именем foo
в текущем каталоге или ниже, а затем *(^/)
соответствует любому файлу в этих foo
каталогах.. (^/)
в конце является квалификатором glob, который ограничивает шаблон от сопоставления каталогов. (используйте (.)
для сопоставления только с обычными файлами или (-.)
для включения символических ссылок на обычные файлы ).
Вbash
:
shopt -s globstar nullglob
for pathname in **/foo/*; do
if [[ ! -d "$pathname" ]] || [[ -h "$pathname" ]]; then
printf '%s\n' "$pathname"
fi
done
Я установил опцию nullglob
в bash
для полного удаления шаблона, если он не соответствует ничему . Параметр оболочки globstar
позволяет использовать **
в bash
(, по умолчанию он включен вzsh
).
Поскольку bash
не имеет квалификаторов glob zsh
,Я перебираю пути, которым соответствует шаблон, и проверяю каждое совпадение, чтобы убедиться, что это не каталог, прежде чем печатать его. Измените тест " ! -d || -h
" на тест " -f && ! -h
", чтобы вместо этого выбирать только обычные файлы, или только один тест " -f
", чтобы также печатать символические ссылки на обычные файлы.
Пробовали с подходом «Ниже»
find . -type d -iname "*foo* -exec ls -ltr {} \; 2>/dev/null| awk '!/^d/||/^l/{print $0}'
Первое, что приходит на ум:
find $ROOT_PATH -type d -name foo | xargs -n1 -I{} find {} -type f
Если вы можете гарантировать, что имена файлов и каталогов не будут содержать символы новой строки, один из способов — найти все файлы, а затем использовать grep
для поиска только нужных результатов:
find. -type f | grep '/foo/[^/]*$'
Я использую RHEL 7. У меня работает:
find. -path "*/foo/*" ! -path '*/foo/*/*' -type f
Обратите внимание на точку перед путем -. (Или подставьте туда свой путь, например, /home/$USER)
DOT говорит: «Начать поиск в текущем каталоге»
путь-говорит: «Ищите что угодно, за которым следует подкаталог -с именем foo, за которым следует что угодно», за исключением каталогов, вложенных в «foo».
Тип-f говорит: дайте мне только файлы в соответствующем каталоге.
Похоже на
-path "*/foo/*" ! -path '*/foo/*/*'
Не получает все, так как пропускает такие вещи, как ./a/foo/b/foo/c
.
Если вы можете гарантировать, что имена файлов и каталогов не будут содержать символы новой строки, вы можете опубликовать -обработку вывода с помощью awk
, например:
find. -path "*/foo/*" -type f | awk -F/ '$(NF-1) == "foo"'
**
не имеет особого значения в паттернах find
. -path '*/foo/*'
найдет все файлы в каталоге с именем foo
, включая файлы в подкаталогах. -path '*/foo/*' ! -path '*/foo/*/*'
исключит такие файлы, как a/foo/b/foo/c
. Я не думаю, что вы можете сделать это всего одним вызовом POSIX find
.
С find
реализациями, поддерживающими-regex
(GNU, BusyBox, FreeBSD, NetBSD ), вы можете использовать это, чтобы убедиться, что после foo
стоит один /
.
find. -regex '.*/foo/[^/]*' -type f
Кроме того, вы можете использовать find
для поиска каталогов foo
и оболочки для перечисления файлов в этом каталоге.
Другим потенциальным подходом может быть повторный вызов find
, но я не могу найти find
чистое POSIX-решение, которое действительно работает. С любым POSIX find
, вызывается снова для каждого каталога foo
:
find. -name foo -type d -exec find {} -type d ! -name foo -prune -o -type f \;
Имейте в виду, что это в основном работает, но не совсем, и это немного хрупко. Вам нужно -type d -prune
, чтобы избежать рекурсии в подкаталоги, но только с -type d -prune
find остановится на каталоге foo
. ! -name foo
не обрезает foo/foo
, поэтому о файле, подобном foo/foo/bar
, будет сообщено дважды. Вы не можете использовать -exec
во внутреннем find
, потому что его {}
будет интерпретироваться внешним find
. Если ваш find
имеет -maxdepth
(, который рассматривается для включения в следующую версию POSIX ), вы можете сделать его надежным, но все еще существует это ограничение в отношении-exec
:
find. -name foo -type d -exec find {} -maxdepth 1 -type f \;
С любым POSIX find и sh:
find. -name foo -type d -exec sh -c '
for x in "$0/"* "$0/".*; do
if [ -f "$x" ] && ! [ -L "$x" ]; then
…;
fi;
done
' {} \;
Замените код, который вы хотите запустить в именах файлов, на …
.