web-dev-qa-db-fra.com

Imbrication si dans une boucle for

Je suis assez nouveau dans les scripts bash, donc c'est probablement une erreur de syntaxe stupide, mais pourquoi ce code ne fonctionne-t-il pas?

for x in $(ls)
do
  if [ -d $x ]
  then
  echo $x
  fi
done

La section séparée pour et si fonctionne correctement, mais cela ne produit aucune sortie.

21
James Jenkinson

Deux choses. N'utilisez jamais ls pour parcourir les fichiers et citez les extensions de paramètres "$x". La syntaxe for et if elle-même est correcte. Je préfère mettre les do et then sur la même ligne

for file in *; do
    if [[ -d "$file" ]]; then
        echo "$file is a directory"
    Elif [[ -f "$file" ]]; then
        echo "$file is a regular file"
    fi
done

Pour apprendre bash, je recommande de lire http://mywiki.wooledge.org/BashGuide la plupart des autres tutoriels et guides ne sont malheureusement pas très bons.

La raison de ne pas faire for x in $(ls) pour itérer les fichiers est que for itère les mots et ls affiche des lignes avec des noms de fichiers. s'il se trouve que ces noms de fichiers contiennent des espaces, ces noms de fichiers seront divisés en mots, de sorte que vous itérerez les mots des noms de fichiers, pas les noms de fichiers. Évidemment, pour les cas simples qui fonctionnent, mais pourquoi utiliser une solution à moitié fonctionnelle alors qu'il existe une manière plus courte et plus élégante de gérer tous les cas?

Avec for x in *, Le shell remplace le * Par tous les noms de fichiers correspondant à ce modèle dans le répertoire actuel (appelé extension de nom de chemin), et chaque nom de fichier sera un mot distinct, donc cela fonctionnera quels que soient les caractères le nom de fichier contient. Les noms de fichiers peuvent contenir n'importe quel caractère (y compris les sauts de ligne), à ​​l'exception de / Et de l'octet NUL (\ 0).

Voir http://mywiki.wooledge.org/ParsingLs pour en savoir plus.

Quant à l'utilisation de [[ Vs [. [ Est une commande héritée du Bourne Shell, utilisée pour tester des chaînes, des fichiers et des nombres. Bash a ajouté un mot clé [[ Plus puissant qui peut faire tout ce que [ Peut et plus encore. Si vous écrivez un script sh, vous devez utiliser [, Mais dans les scripts bash, vous devez utiliser les syntaxes [[ Et (( Plus puissantes. Voir http://mywiki.wooledge.org/BashFAQ/031 pour en savoir plus sur la différence entre [ Et [[.

24
geirha

Peut-être qu'il y a un problème avec les caractères utilisés pour séparer les différentes parties de la déclaration?

Et si vous essayiez:

for x in $(ls); do if [ -d $x ]; then echo $x; fi; done

Cela produit-il une sortie?

5
imm

1) la syntaxe est parfaitement légale

2) Oui, vous pouvez imbriquer des blocs "if/else" dans une boucle. Vous pouvez également imbriquer des boucles internes dans une boucle externe :)

3) "if [-d $ x]" vérifie si "x" est un "répertoire".

Si vous ne voyez aucune sortie, alors vous n'avez peut-être pas de sous-répertoires?

SUGGESTION:

  • ouvrir une fenêtre de terminal

  • Exécutez votre script. Voyez si vous obtenez ou non une sortie.

  • Sinon, saisissez mkdir moose. Cela créera un sous-répertoire appelé (par hasard) "orignal".

  • Relancez votre script. Vous devriez voir au moins "orignal".

1
paulsm4