Ответы:
Вы можете указать косую черту в конце, чтобы соответствовать только каталогам:
for d in */ ; do
echo "$d"
done
[[ -L $d ]]
, является ли $ d символической ссылкой.
set -P
влияет только на команды, которые меняют каталог. sprunge.us/TNac
[[ -L "$f" ]]
не исключать символические ссылки в этом случае с */
, вы должны удалить косую черту с [[ -L "${f%/}" ]]
(см. Тест для связи с косой чертой )
Вы можете проверить с -d
:
for f in *; do
if [ -d "$f" ]; then
# $f is a directory
fi
done
Это один из операторов проверки файлов .
if [[ -d "$f" && ! -L "$f" ]]
исключит символические
if [[ "$f" = "*" ]]; then continue; fi
Помните, что решение 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
является ли каталог каталогом, а затем выводить эхо, f
если условие возвращает true. Если f
равно */
, echo $f
не будет выполняться.
shopt -s nullglob
.
Если вам нужно выбрать более конкретные файлы, чем использовать только каталоги find
и передать их while read
:
shopt -s dotglob
find * -prune -type d | while IFS= read -r d; do
echo "$d"
done
Используется shopt -u dotglob
для исключения скрытых каталогов (или setopt dotglob
/ unsetopt dotglob
в zsh).
IFS=
чтобы избежать разделения имен файлов, содержащих одно из $IFS
, например:'a b'
см. ответ AsymLabs ниже для большего количества find
вариантов
edit:
Если вам нужно создать выходное значение из цикла while, вы можете обойти дополнительный подоболочек с помощью этого трюка:
while IFS= read -r d; do
if [ "$d" == "something" ]; then exit 1; fi
done < <(find * -prune -type d)
Вы можете использовать чистый bash для этого, но лучше использовать find:
find . -maxdepth 1 -type d -exec echo {} \;
(найти дополнительно будет включать скрытые каталоги)
shopt -s dotglob
для bash
включения скрытых каталогов. Ваш также будет включать .
. Также обратите внимание, что -maxdepth
это не стандартная опция ( -prune
есть).
dotglob
Вариант интересен , но dotglob
относится только к использованию *
. find .
всегда будет включать скрытые каталоги (и текущий каталог)
Это делается для поиска как видимых, так и скрытых каталогов в текущем рабочем каталоге, исключая корневой каталог:
просто перебрать каталоги:
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 и т. д.
... -print0 | xargs -0 ...
если вы не знаете, каковы точные имена.
find * | while read file; do ...
Вы можете перебрать все каталоги, включая скрытые каталоги (начиная с точки) в одну строку и несколько команд с помощью:
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
в зш)
Вы можете сбросить дотглоб с
shopt -u dotglob
Это будет включать полный путь в каждом каталоге в списке:
for i in $(find $PWD -maxdepth 1 -type d); do echo $i; done
Используйте find
с, -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
Вы можете установить его как псевдоним
ls
ответа, основанного на списках каталогов.
ls
: mywiki.wooledge.org/ParsingLs