0
votes

Comment créer une commande qui affiche tous les répertoires, via un script shell?

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.


0 commentaires

3 Réponses :


1
votes

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é.


1 commentaires

Bien que cela puisse être une réponse appropriée, j'aimerais trouver l'erreur dans mon fichier rep.sh déjà existant.



1
votes

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.


2 commentaires

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 .



0
votes

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.


0 commentaires