Risposte:
È possibile specificare una barra alla fine per abbinare solo le directory:
for d in */ ; do
echo "$d"
done
[[ -L $d ]]
se $ d è un collegamento simbolico.
set -P
influisce solo sui comandi che cambiano directory. sprunge.us/TNac
[[ -L "$f" ]]
in questo caso non escluderemo i collegamenti simbolici con */
, devi eliminare la barra finale [[ -L "${f%/}" ]]
(vedi Test per il collegamento con barra finale )
Puoi provare con -d
:
for f in *; do
if [ -d "$f" ]; then
# $f is a directory
fi
done
Questo è uno degli operatori di test dei file .
if [[ -d "$f" && ! -L "$f" ]]
escluderà i
if [[ "$f" = "*" ]]; then continue; fi
Attenzione che la soluzione di choroba, sebbene elegante, può suscitare comportamenti imprevisti se non ci sono directory disponibili nella directory corrente. In questo stato, anziché saltare il for
ciclo, bash eseguirà il ciclo esattamente una volta dove d
è uguale a */
:
#!/usr/bin/env bash
for d in */; do
# Will print */ if no directories are available
echo $d
done
Ti consiglio di utilizzare quanto segue per proteggere da questo 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
Questo codice eseguirà il ciclo attraverso tutti i file nella directory corrente, verificando se si f
tratta di una directory, quindi echo f
se la condizione ritorna vera. Se f
è uguale a */
, echo $f
non verrà eseguito.
shopt -s nullglob
.
Se è necessario selezionare file più specifici di quelli utilizzati solo dalle directory find
e passarli a while read
:
shopt -s dotglob
find * -prune -type d | while IFS= read -r d; do
echo "$d"
done
Utilizzare shopt -u dotglob
per escludere directory nascoste (o setopt dotglob
/ unsetopt dotglob
in zsh).
IFS=
per evitare la divisione di nomi di file contenenti uno dei $IFS
, ad esempio:'a b'
vedi AsymLabs risposta sotto per ulteriori find
opzioni
modifica:
Nel caso in cui sia necessario creare un valore di uscita all'interno del ciclo while, è possibile aggirare la subshell aggiuntiva con questo trucco:
while IFS= read -r d; do
if [ "$d" == "something" ]; then exit 1; fi
done < <(find * -prune -type d)
Puoi usare pure bash per questo, ma è meglio usare find:
find . -maxdepth 1 -type d -exec echo {} \;
(trova inoltre includerà directory nascoste)
shopt -s dotglob
per bash
includere directory nascoste. Il tuo includerà anche .
. Si noti inoltre che -maxdepth
non è un'opzione standard ( -prune
è).
dotglob
opzione è interessante ma dotglob
si applica solo all'uso di *
. find .
includerà sempre le directory nascoste (e anche la directory corrente)
Questo viene fatto per trovare sia le directory visibili che quelle nascoste nella presente directory di lavoro, esclusa la directory principale:
per scorrere semplicemente le directory:
find -path './*' -prune -type d
per includere collegamenti simbolici nel risultato:
find -L -path './*' -prune -type d
fare qualcosa per ogni directory (esclusi i collegamenti simbolici):
find -path './*' -prune -type d -print0 | xargs -0 <cmds>
per escludere directory nascoste:
find -path './[^.]*' -prune -type d
per eseguire più comandi sui valori restituiti (un esempio molto inventato):
find -path './[^.]*' -prune -type d -print0 | xargs -0 -I '{}' sh -c \
"printf 'first: %-40s' '{}'; printf 'second: %s\n' '{}'"
invece di 'sh -c' può anche usare 'bash -c', ecc.
... -print0 | xargs -0 ...
se non sai quali sono i nomi esatti.
find * | while read file; do ...
Puoi scorrere tutte le directory incluse le directory nascoste (che iniziano con un punto) in una riga e più comandi con:
for file in */ .*/ ; do echo "$file is a directory"; done
Se si desidera escludere i collegamenti simbolici:
for file in *; do
if [[ -d "$file" && ! -L "$file" ]]; then
echo "$file is a directory";
fi;
done
nota: l' uso dell'elenco */ .*/
funziona in bash, ma mostra anche le cartelle .
e ..
mentre in zsh non le mostrerà ma genererà un errore se non ci sono file nascosti nella cartella
Una versione più pulita che includerà directory nascoste ed escluderà ../ sarà con l'opzione dotglob:
shopt -s dotglob
for file in */ ; do echo "$file is a directory"; done
(o setopt dotglob
in zsh)
puoi deselezionare dotglob con
shopt -u dotglob
Ciò includerà il percorso completo in ciascuna directory nell'elenco:
for i in $(find $PWD -maxdepth 1 -type d); do echo $i; done
Utilizzare find
con -exec
per scorrere ciclicamente le directory e chiamare una funzione nell'opzione exec:
dosomething () {
echo "doing something with $1"
}
export -f dosomething
find -path './*' -prune -type d -exec bash -c 'dosomething "$0"' {} \;
Utilizzare shopt -s dotglob
o shopt -u dotglob
per includere / escludere directory nascoste
ls -l | grep ^d
o:
ll | grep ^d
Puoi impostarlo come alias
ls
risposta basata su, che elenca le directory.
ls
: mywiki.wooledge.org/ParsingLs