Respostas:
Você pode especificar uma barra no final para corresponder apenas aos diretórios:
for d in */ ; do
echo "$d"
done
[[ -L $d ]]
se $ d é um link simbólico.
set -P
afeta apenas comandos que alteram o diretório. sprunge.us/TNac
[[ -L "$f" ]]
não excluir links simbólicos neste caso com */
, você tem que tirar a barra final com [[ -L "${f%/}" ]]
(veja Testar link com barra invertida )
Você pode testar com -d
:
for f in *; do
if [ -d "$f" ]; then
# $f is a directory
fi
done
Este é um dos operadores de teste de arquivo .
if [[ -d "$f" && ! -L "$f" ]]
excluirá links simbólicos
if [[ "$f" = "*" ]]; then continue; fi
Cuidado que a solução do choroba, embora elegante, pode provocar um comportamento inesperado se nenhum diretório estiver disponível no diretório atual. Nesse estado, em vez de pular o for
loop, o bash executará o loop exatamente uma vez onde d
for igual a */
:
#!/usr/bin/env bash
for d in */; do
# Will print */ if no directories are available
echo $d
done
Eu recomendo usar o seguinte para proteger contra este caso:
#!/usr/bin/env bash
for f in *; do
if [ -d ${f} ]; then
# Will not run if no directories are available
echo $f
fi
done
Esse código percorrerá todos os arquivos no diretório atual, verificará se f
é um diretório e ecoará f
se a condição retornar verdadeira. Se f
for igual a */
, echo $f
não será executado.
shopt -s nullglob
.
Se você precisar selecionar arquivos mais específicos do que apenas os diretórios usam find
e passá-los para while read
:
shopt -s dotglob
find * -prune -type d | while IFS= read -r d; do
echo "$d"
done
Use shopt -u dotglob
para excluir diretórios ocultos (ou setopt dotglob
/ unsetopt dotglob
no zsh).
IFS=
para evitar a divisão de nomes de arquivos que contenham um dos $IFS
, por exemplo:'a b'
veja a resposta do AsymLabs abaixo para mais find
opções
edit:
Caso você precise criar um valor de saída a partir do loop while, é possível contornar o subshell extra com este truque:
while IFS= read -r d; do
if [ "$d" == "something" ]; then exit 1; fi
done < <(find * -prune -type d)
Você pode usar o bash puro para isso, mas é melhor usar o find:
find . -maxdepth 1 -type d -exec echo {} \;
(encontrar adicionalmente incluirá diretórios ocultos)
shopt -s dotglob
para bash
incluir diretórios ocultos. O seu também incluirá .
. Observe também que -maxdepth
não é uma opção padrão ( -prune
é).
dotglob
opção é interessante, mas dotglob
só se aplica ao uso de *
. find .
incluirá sempre diretórios ocultos (eo dir atual, bem)
Isso é feito para localizar os diretórios visíveis e ocultos no atual diretório de trabalho, excluindo o diretório raiz:
apenas percorrer os diretórios:
find -path './*' -prune -type d
para incluir links simbólicos no resultado:
find -L -path './*' -prune -type d
para fazer algo em cada diretório (excluindo links simbólicos):
find -path './*' -prune -type d -print0 | xargs -0 <cmds>
excluir diretórios ocultos:
find -path './[^.]*' -prune -type d
para executar vários comandos nos valores retornados (um exemplo muito artificial):
find -path './[^.]*' -prune -type d -print0 | xargs -0 -I '{}' sh -c \
"printf 'first: %-40s' '{}'; printf 'second: %s\n' '{}'"
em vez de 'sh -c' também pode usar 'bash -c', etc.
... -print0 | xargs -0 ...
se você não souber quais são os nomes exatos.
find * | while read file; do ...
Você pode percorrer todos os diretórios, incluindo os diretórios ocultos (começando com um ponto) em uma linha e vários comandos com:
for file in */ .*/ ; do echo "$file is a directory"; done
Se você deseja excluir links simbólicos:
for file in *; do
if [[ -d "$file" && ! -L "$file" ]]; then
echo "$file is a directory";
fi;
done
note: o uso da lista */ .*/
funciona no bash, mas também exibe as pastas .
e, ..
enquanto estiver no zsh, não as mostrará, mas gerará um erro se não houver um arquivo oculto na pasta
Uma versão mais limpa que incluirá diretórios ocultos e excluirá ../ estará com a opção dotglob:
shopt -s dotglob
for file in */ ; do echo "$file is a directory"; done
(ou setopt dotglob
em zsh)
você pode desabilitar o dotglob com
shopt -u dotglob
Isso incluirá o caminho completo em cada diretório da lista:
for i in $(find $PWD -maxdepth 1 -type d); do echo $i; done
Use find
with -exec
para percorrer os diretórios e chamar uma função na opção exec:
dosomething () {
echo "doing something with $1"
}
export -f dosomething
find -path './*' -prune -type d -exec bash -c 'dosomething "$0"' {} \;
Use shopt -s dotglob
ou shopt -u dotglob
para incluir / excluir diretórios ocultos
ls -d */ | while read d
do
echo $d
done
This
is
one
directory
with
spaces
in
the
name
- mas é analisado como múltiplo.
ls -l | grep ^d
ou:
ll | grep ^d
Você pode configurá-lo como um alias
ls
da resposta com base nessa lista , que lista os diretórios.
ls
: mywiki.wooledge.org/ParsingLs