Відповіді:
Ви можете вказати косу рису в кінці, щоб відповідати лише каталогів:
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
Остерігайтеся, що рішення хороби, хоч і елегантне, може викликати несподіване поведінку, якщо в поточному каталозі відсутні каталоги. У такому стані, замість того, щоб пропускати 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
якщо умова повертається як справжня. Якщо 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
варіантів
редагувати:
Якщо вам потрібно створити значення виходу з циклу 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
в zsh)
ви можете відключити 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