Je voudrais créer une commande qui montre tous les répertoires dans le répertoire donné en paramètre. Par exemple, si notre hiérarchie de fichiers est comme telle:
function rep(){ all=`ls $1` for each in $all do if [ -d $each ] then echo $each fi done }
Alors le résultat de rep dir1
doit afficher:
dir5
Alors que rep dir1 / dir4
devrait afficher:
dir2 dir3 dir4
Pour le moment, j'ai un script shell rep.sh code > faire ce qui suit:
dir1: dir2 dir3 file1 dir4: file2 dir5
L'exécution de ce script via bash rep.sh
ne fait rien, ce que je suppose est correct, mais alors quand Je fais rep dir1
ou rep dir1 / dir4
cela ne montre rien. Je pense que mon erreur réside dans le fait que je n'utilise pas correctement l'environnement des fonctions, ou que je ne passe pas les arguments correctement.
3 Réponses :
Vous pouvez utiliser find
et basename
pour cela.
... find "$1" -mindepth 1 -maxdepth 1 -type d -exec basename {} \; ...
Les options -mindepth 1
et -maxdepth 1
empêchent de lister le répertoire de base ou de descendre dans les sous-répertoires. -type d
applique un filtre afin que seuls les répertoires soient répertoriés et -exec basename {} \;
exécute basename
pour l'élément trouvé. basename
supprime le chemin afin que seul le nom du répertoire lui-même soit imprimé.
Bien que cela puisse être une réponse appropriée, j'aimerais trouver l'erreur dans mon fichier rep.sh déjà existant.
En pur Bash:
$ all=$(ls "$1") $ declare -p all declare -- all="dir2 dir3 dir4 file1"
Le glob "$ 1" / * /
obtient tous les répertoires; les deux extensions de paramètres suppriment ensuite la barre oblique de fin et le chemin vers les répertoires.
Ceci ignore les répertoires cachés; si vous les voulez aussi, vous devez activer l'option shell dotglob
. Pour conserver le paramétrage de cette option shell, vous pouvez encapsuler la fonction comme ceci:
rep() { local dg # Get current dotglob setting dg=$(shopt -p dotglob) # Enable dotglob shopt -s dotglob for dir in "$1"/*/; do dir=${dir%/} printf '%s\n' "${dir##*/}" done # Set dotglob back to what it was $dg }
Quant à savoir pourquoi votre script ne fonctionne pas: jetez un œil à ce qui contenu dans all
après que vous lui ayez attribué.
rep() { for dir in "$1"/*/; do dir=${dir%/} printf '%s\n' "${dir##*/}" done }
(Notez que j'ai également remplacé les backticks obsolètes par $ () et double guillemets
$1
.)
La sortie de ls
ne contient pas les chemins vers les répertoires, c'est pourquoi votre -d
test renvoie faux pour tout.
Utiliser ls
comme vous le faites est très sujet aux erreurs: le fractionnement de mots et l'expansion des paramètres font échouer un tel script pour n'importe quel nom de fichier avec un vide ou un métacaractère shell (voir Pourquoi vous ne devriez pas analyser la sortie de ls (1)
). Utilisez plutôt des globes.
Cela ne marche pas. Quand je fais bash rep.sh, puis rep dir1 il ne montre rien, dois-je faire autre chose?
@ J.Schmidt Vous devez d'abord rechercher le fichier contenant la fonction: . rep.sh
, puis utilisez la fonction rep dir1
.
Trois erreurs:
1) l'utilisation de
function rep(){ all="$1"/* for each in $all do if [ -d $each ] then echo $each fi done } rep $1
au lieu de
all="$1"/*
que @Benjamin W. souligné.
2) J'ai oublié de mettre rep $ 1
à la fin de mon fichier rep.sh
. Le fichier ressemble donc à:
all=`ls $1`
3) Dans la ligne de commande, je dois mettre alias rep = "bash rep.sh"
pour être capable d'utiliser la commande rep
librement dans la ligne de commande.