Как мне перебирать только каталоги в bash?

У меня есть папка с некоторыми каталогами и некоторыми файлами (некоторые скрыты, начиная с точки).

for d in *; do echo $d done 

будет проходить через все файлы, но я хочу, чтобы цикл был только через каталоги. Как мне это сделать?

11 Solutions collect form web for “Как мне перебирать только каталоги в bash?”

Вы можете указать косую черту в конце, чтобы соответствовать только каталогам:

 for d in */ ; do echo "$d" done 

Вы можете проверить с помощью -d :

 for f in *; do if [[ -d $f ]]; then # $f is a directory fi done 

Это один из операторов проверки файлов .

Вы можете использовать чистый bash для этого, но лучше использовать find:

 find . -maxdepth 1 -type d -exec echo {} \; 

(найти дополнительно будет включать скрытые каталоги)

Если вам нужно выбрать более конкретные файлы, чем только каталоги, используйте find и передайте его во while read :

 shopt -s dotglob find * -prune -type d | while IFS= read -rd; do echo "$d" done 

Используйте shopt -u dotglob чтобы исключить скрытые каталоги (или setopt dotglob / unsetopt dotglob в zsh).

IFS= чтобы избежать разбиения имен файлов, содержащих один из $IFS , например: 'a b'

см. AsymLabs ниже для получения дополнительных параметров find


редактировать:
Если вам нужно создать значение выхода из цикла while, вы можете обойти дополнительную подоболочку с помощью этого трюка:

 while IFS= read -rd; do if [ "$d" == "something" ]; then exit 1; fi done < <(find * -prune -type d) 

Помните, что решение choroba, хотя и изящно, может вызвать неожиданное поведение, если в текущем каталоге отсутствуют каталоги. В этом состоянии, а не пропускании цикла for , bash будет запускать цикл точно один раз, где d равно */ :

 #!/usr/bin/env bash for d in */; do # Will print */ if no directories are available echo $d done 

Я рекомендую использовать следующее для защиты от этого случая:

 #!/usr/bin/env bash for f in *; do if [ -d ${f} ]; then # Will not run if no directories are available echo $f fi done 

Этот код будет проходить через все файлы в текущем каталоге, проверьте, является ли f каталогом, а затем echo f если условие возвращает true. Если f равно */ , echo $f не будет выполняться.

Это делается для поиска как видимых, так и скрытых каталогов в текущем рабочем каталоге, за исключением корневого каталога:

просто прокрутить каталоги:

  find -path './*' -prune -type d 

включить символические ссылки в результат:

 find -L -path './*' -prune -type d 

делать что-то в каждом каталоге (исключая символические ссылки):

 find -path './*' -prune -type d -print0 | xargs -0 <cmds> 

для исключения скрытых каталогов:

 find -path './[^.]*' -prune -type d 

для выполнения нескольких команд по возвращаемым значениям (очень надуманный пример):

 find -path './[^.]*' -prune -type d -print0 | xargs -0 -I '{}' sh -c \ "printf 'first: %-40s' '{}'; printf 'second: %s\n' '{}'" 

вместо «sh -c» также можно использовать «bash -c» и т. д.

Вы можете прокручивать все каталоги, включая скрытые каталоги (начиная с точки) в одной строке и несколько команд с помощью:

 for file in */ .*/ ; do echo "$file is a directory"; done 

Если вы хотите исключить символические ссылки:

 for file in *; do if [[ -d "$file" && ! -L "$file" ]]; then echo "$file is a directory"; fi; done 

примечание: использование списка */ .*/ работает в bash, но также отображает папки . и .. то время как в zsh он не будет показывать их, но выдает ошибку, если в папке нет скрытого файла

Чистая версия, которая будет включать скрытые каталоги и исключить ../, будет с опцией dotglob:

 shopt -s dotglob for file in */ ; do echo "$file is a directory"; done 

(или setopt dotglob в zsh)

вы можете отключить dotglob с помощью

 shopt -u dotglob 

Это будет включать полный путь в каждый каталог в списке:

 for i in $(find $PWD -maxdepth 1 -type d); do echo $i; done 
 ls -d */ | while read d do echo $d done 

Используйте find с -exec для циклического -exec по каталогам и вызова функции в опции exec:

 dosomething () { echo "doing something with $1" } export -f dosomething find -path './*' -prune -type d -exec bash -c 'dosomething "$0"' {} \; 

Используйте shopt -s dotglob или shopt -u dotglob для включения / исключения скрытых каталогов

 ls -l | grep ^d 

или:

 ll | grep ^d 

Вы можете установить его как псевдоним

  • поиск всех слов в текстовом файле, появляющемся в другом текстовом файле
  • Где мои данные 7za записываются в
  • Bash-скрипт, обнаруживающий изменение в файлах из каталога
  • Как предоставить разные разрешения для каждого пользователя?
  • Список всех файлов, заканчивающихся несколькими расширениями файлов?
  • Используются ли значения limits.conf для каждого процесса?
  • Определите, был ли файл изменен
  • Как создать структурированный список всех файлов и каталогов в определенном каталоге (рекурсивно)?
  • множественное преобразование bam to bed с использованием постельных принадлежностей
  • Есть ли способ скопировать весь файл в одну конкретную подпапку в одной родительской папке?
  • Может ли cp переопределять подкаталоги с тем же именем?
  • Linux и Unix - лучшая ОС в мире.