Найти все файлы в каталогах с именем foo

Вы можете хорошо использовать целевую -функцию значения переменной здесь:

build_x: version := latest
build_x:
     @echo "Building version $(version)"
3
17.09.2019, 21:47
6 ответов

Не использовать 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", чтобы также печатать символические ссылки на обычные файлы.

6
27.01.2020, 21:08

Пробовали с подходом «Ниже»

find . -type d -iname "*foo* -exec ls -ltr {} \; 2>/dev/null| awk '!/^d/||/^l/{print $0}'
-2
27.01.2020, 21:08

Первое, что приходит на ум:

find $ROOT_PATH -type d -name foo | xargs -n1 -I{} find {} -type f

0
27.01.2020, 21:08

Если вы можете гарантировать, что имена файлов и каталогов не будут содержать символы новой строки, один из способов — найти все файлы, а затем использовать grepдля поиска только нужных результатов:

find. -type f | grep '/foo/[^/]*$'
2
27.01.2020, 21:08

Я использую 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"'
3
27.01.2020, 21:08

** не имеет особого значения в паттернах 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 -prunefind остановится на каталоге 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
' {} \;

Замените код, который вы хотите запустить в именах файлов, на .

3
27.01.2020, 21:08

Теги

Похожие вопросы