Ik werk aan een script dat een actie moet uitvoeren in elke submap van een specifieke map.
Wat is de meest efficiënte manier om dat te schrijven?
Antwoord 1, autoriteit 100%
Een versie die het maken van een subproces vermijdt:
for D in *; do
if [ -d "${D}" ]; then
echo "${D}" # your processing here
fi
done
Of, als uw actie een enkele opdracht is, is dit beknopter:
for D in *; do [ -d "${D}" ] && my_command; done
Of een nog beknoptere versie (bedankt @enzotib). Merk op dat in deze versie elke waarde van D
een afsluitende slash heeft:
for D in */; do my_command; done
Antwoord 2, autoriteit 59%
for D in `find . -type d`
do
//Do whatever you need with D
done
Antwoord 3, autoriteit 40%
De eenvoudigste niet recursievemanier is:
for d in */; do
echo "$d"
done
De /
aan het einde vertelt, gebruik alleen mappen.
Het is niet nodig
- vinden
- awk
- …
Antwoord 4, autoriteit 7%
Gebruik de opdracht find
.
In GNU find
kunt u de parameter -execdir
gebruiken:
find . -type d -execdir realpath "{}" ';'
of door de parameter -exec
te gebruiken:
find . -type d -exec sh -c 'cd -P "$0" && pwd -P' {} \;
of met xargs
commando:
find . -type d -print0 | xargs -0 -L1 sh -c 'cd "$0" && pwd && echo Do stuff'
Of gebruik forlus:
for d in */; { echo "$d"; }
Voor recursiviteit, probeer in plaats daarvan uitgebreide globbing (**/
) (inschakelen door: shopt -s extglob
).
Voor meer voorbeelden, zie: Hoe ga je naar elke map en voer je een commando uit?bij SO
Antwoord 5, autoriteit 4%
Handige oneliners
for D in *; do echo "$D"; done
for D in *; do find "$D" -type d; done ### Option A
find * -type d ### Option B
Optie A is juist voor mappen met spaties ertussen. Over het algemeen ook sneller omdat het niet elk woord in een mapnaam als een afzonderlijke entiteit afdrukt.
# Option A
$ time for D in ./big_dir/*; do find "$D" -type d > /dev/null; done
real 0m0.327s
user 0m0.084s
sys 0m0.236s
# Option B
$ time for D in `find ./big_dir/* -type d`; do echo "$D" > /dev/null; done
real 0m0.787s
user 0m0.484s
sys 0m0.308s
Antwoord 6, autoriteit 3%
find . -type d -print0 | xargs -0 -n 1 my_command
Antwoord 7, autoriteit 2%
Hierdoor wordt een subshell gemaakt (wat betekent dat variabelewaarden verloren gaan wanneer de while
-lus wordt afgesloten):
find . -type d | while read -r dir
do
something
done
Dit zal niet:
while read -r dir
do
something
done < <(find . -type d)
Beide werken als er spaties zijn in directorynamen.
Antwoord 8, autoriteit 2%
Je zou kunnen proberen:
#!/bin/bash
### $1 == the first args to this script
### usage: script.sh /path/to/dir/
for f in `find . -maxdepth 1 -mindepth 1 -type d`; do
cd "$f"
<your job here>
done
of vergelijkbaar…
Uitleg:
find . -maxdepth 1 -mindepth 1 -type d
:
Vind alleen mappen met een maximale recursieve diepte van 1 (alleen de submappen van $1) en een minimale diepte van 1 (exclusief huidige map .
)
Antwoord 9, autoriteit 2%
het geaccepteerde antwoord wordt onderbroken door spaties als de directorynamen die hebben, en de voorkeurssyntaxis is $()
voor bash/ksh. Gebruik GNU find
-exec
optie met +;
bijv.
find .... -exec mycommand +;
#this is same as passing to xargs
of gebruik een while-lus
find .... | while read -r D
do
# use variable `D` or whatever variable name you defined instead here
done