Itérer sur la variable $ PATH en utilisant un script shell

Si je tape echo $PATH dans le terminal, j’obtiens le résultat suivant:

 /usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/home/fnorbert/.local/bin:/home/fnorbert/bin 

Je veux parcourir ces chemins en utilisant un script shell, mais je ne sais pas comment faire.
J’ai essayé ce qui suit:

 for i in 1 2 3 do echo $PATH | cut -d':' -f$i done 

Cela imprime les trois premiers chemins, mais je veux représenter chaque chemin avec la variable i si cela est possible.

Vous pouvez utiliser read avec le délimiteur défini comme :

 while read -d ':' p; do echo "$p" done <<< "$PATH:" 

Le moyen le plus simple est probablement de changer IFS en deux points et de laisser le fractionnement du mot le faire:

 IFS=: for p in $PATH ; do echo "$p" done 

Mais cela pourrait déclencher la globalisation du nom de fichier, dans le cas étrange où votre PATH contenait des caractères tels que *?[] . Vous devez utiliser set -f pour éviter cela.

Bien que la modification de l’ IFS puisse être considérée comme problématique de toute façon, cela affecte le rest du script. Donc, dans Bash, nous pourrions simplement diviser les chemins en un tableau avec read -a , cela ne pose pas de problème avec les caractères globaux:

 IFS=: read -a paths <<< "$PATH" for p in "${paths[@]}" ; do echo "$p" done 

avec écho:

 echo "${PATH//:/$'\n'}" 

sed:

 sed 's/:/\n/g' <<< "$PATH" 

tr:

 tr ':' '\n' <<< "$PATH" 

python:

 python -c "import os; print os.environ['PATH'].replace(':', '\n')" 

pour itérer utilisation pour:

 for in in ${PATH//:/ }; do echo $i; done 

Voici une solution sortingviale, qui étend un peu votre tentative

 for i in $( echo "$PATH" | cut -d: -f 1- --output-delimiter=" " ) ; do echo "$i" ; done 

Une astuce utilisée ici est -f 1- pour spécifier tous les champs au lieu d’un seul.

Une autre astuce consiste à utiliser l’option --output-delimiter .

Cette solution souffre de la sensibilité aux caractères spéciaux dans les noms de répertoire.

Considérons l’exemple suivant

 PATH="help me":\*:now for i in $( echo "$PATH" | cut -d: -f 1- --output-delimiter=" " ) ; do echo "$i" ; done 

Cela sortirait

 help me foo now 

C’est,

  • les espaces dans les noms de répertoire ne seront pas traités correctement
  • les caractères spéciaux, tels que * seront développés par le shell dans une liste de fichiers dans le répertoire en cours ( foo est le nom d’un fichier résidant dans le répertoire en cours)

Mais si votre PATH ne contient rien de spécial, cela fonctionnerait. Sinon ou plutôt dans tous les cas, prenez la solution qui utilise read .

Vous pouvez utiliser awk pour l’exigence,

 echo $PATH | awk -F: '{ for (i=1; i<=NF; i++) {print $i}}' 

C'est très efficace dans la performance.