71 votes

Comment afficher $PATH comme un répertoire par ligne ?

Je n'arrive pas à trouver comment lister les différents chemins d'accès dans $PATH séparément pour qu'ils ressemblent à ceci :

/bin
/usr/bin
/usr/local/bin

Comment cela peut-il être fait ?

7voto

Sergiy Kolodyazhnyy Points 97292

Dans cette réponse :

  1. C
  2. Python
  3. Ruby
  4. Alternative awk

1. C

Puisque tous les langages de script ont déjà été utilisés, je vais choisir le C. Il est assez facile d'obtenir des variables d'environnement avec get_env() (voir Documentation sur la bibliothèque C de GNU ). Le reste n'est que manipulation de caractères

bash-4.3$ cat get_path.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
    char *path = getenv("PATH");
    int length = strlen(path) -1;
    for(int i=0;i<=length;i++){
        if (path[i] == ':')
            path[i] = '\n';
        printf("%c",path[i]);
    }
    printf("\n");
    return 0;
}
bash-4.3$ gcc get_path.c
bash-4.3$ ./a.out 
/home/xieerqi/bin
/usr/local/sbin
/usr/local/bin
/usr/sbin
/usr/bin
/sbin
/bin
/usr/games
/usr/local/games
/snap/bin
/opt/microchip/xc16/v1.25/bin
/opt/microchip/xc32/v1.40/bin
/opt/microchip/xc8/v1.35/bin
/home/xieerqi/bin
/home/xieerqi/bin/sh

2. Python

Mais aussi parce que "pourquoi pas", voici une version alternative en Python via les arguments de la ligne de commande. sys.argv

python -c 'import sys; print "\n".join(sys.argv[1].split(":"))' "$PATH"

3. Ruby

Ruby n'est pas livré par défaut avec Ubuntu, contrairement au compilateur C et à l'interpréteur Python, mais si vous vous retrouvez un jour à l'utiliser, la solution en Ruby serait la suivante :

ruby -ne 'puts $_.split(":")' <<< "$PATH"

Comme l'a suggéré 7stud (Merci beaucoup !) dans le cadre de l'enquête sur l'utilisation de l'Internet. commentaires ce qui peut aussi être raccourci avec

ruby -F: -ane 'puts $F' <<<$PATH

et de cette façon

ruby -0072 -ne 'puts chomp' <<<$PATH

4. Alternative awk

Nous pouvons utiliser split() pour décomposer la ligne lue en tableau, et utiliser la fonction for-each boucle pour imprimer chaque élément sur une ligne séparée.

awk '{split($0,arr,":"); for(var in arr) print arr[var]}' <<< $PATH

7voto

Jon Galloway Points 28243

Voici l'équivalent en Go :

$ cat path.go
package main

import (
    "fmt"
    "os"
    "strings"
)

func main() {
    for _, p := range strings.Split(os.Getenv("PATH"), ":") {
        fmt.Println(p)
    }
}

$ go run path.go
/usr/local/sbin
/usr/local/bin
/usr/sbin
/usr/bin
/sbin
/bin
/usr/games
/usr/local/games
/snap/bin
/home/nathan/.local/bin
/home/nathan/go/bin

7voto

Stewart Points 1385

Voici quelques autres approches. J'utilise un PATH avec des répertoires contenant des barres obliques inverses, des espaces et même une nouvelle ligne pour montrer qu'ils devraient fonctionner avec n'importe quoi (à l'exception de la commande cut un qui échoue sur les nouvelles lignes) :

$ echo "$PATH"
/bin:usr/bin/:/usr/local/bin:/some\ horrible thing:/even 
new lines
  • Quelques méthodes Perl :

    $ perl -pe 's/:/\n/g' <<<"$PATH"
    /bin
    usr/bin/
    /usr/local/bin
    /some\ horrible thing
    /even 
    new lines

    El -p signifie "imprimer chaque ligne d'entrée après avoir appliqué le script donné par -e ". Le script utilise l'opérateur de substitution ( s/oldnew/ ) pour remplacer tous les : avec des nouvelles lignes.

    $ perl -lne 'print for split /:/' <<<"$PATH"
    /bin
    usr/bin/
    /usr/local/bin
    /some\ horrible thing
    /even 
    new lines

    El -l ajoute une nouvelle ligne à chaque print appel. Ici, le script divise son entrée sur : puis boucle sur chaque élément fractionné et l'imprime.

    $ perl -F: -ane '$"="\n";print "@F"' <<<"$PATH"
    /bin
    usr/bin/
    /usr/local/bin
    /some\ horrible thing
    /even 
    new lines

    El -a fait perl se comporter comme awk : il divisera chacune de ses lignes d'entrée sur le caractère donné par -F (donc : ici) et sauvegarder le résultat dans le tableau @F . Le site $" est une variable Perl spéciale, le "séparateur de liste", dont la valeur est imprimée entre chaque élément d'une liste imprimée. Ainsi, en lui attribuant la valeur d'un saut de ligne, on obtient print @list imprimer chaque élément de @list et ensuite une nouvelle ligne. Ici, nous l'utilisons pour imprimer @F .

    $ perl -F: -ane 'print join "\n", @F' <<<"$PATH"
    /bin
    usr/bin/
    /usr/local/bin
    /some\ horrible thing
    /even 
    new lines

    Même idée que ci-dessus, mais avec moins de golf. Au lieu d'utiliser $" nous sommes explicitement join en ajoutant des retours à la ligne dans le tableau, puis en imprimant.

  • Simple grep avec la magie du PCRE :

    $ grep -oP '(^|:)\K[^:]+' <<<"$PATH"
    /bin
    usr/bin/
    /usr/local/bin
    /some\ horrible thing
    /even 
    new lines

    El -o fait grep n'imprime que la partie correspondante de chaque ligne, de sorte que chaque correspondance est imprimée sur une ligne distincte. Le site -P permet d'utiliser des expressions régulières compatibles avec Perl (PCRE). La regex recherche des tronçons de caractères non : ( [^:]+ ) qui suivent soit le début de la ligne ( ^ ) ou un : caractère. Le site \K est une astuce de la PCRE qui signifie "écarter tout ce qui correspond à ce point" et qui est utilisée ici pour éviter d'imprimer l'indicateur : également.

  • Et un cut (celle-ci échoue sur les nouvelles lignes, mais peut traiter les barres obliques inversées et les espaces) :

    $ cut -d: -f 1- --output-delimiter=$'\n' <<<"$PATH"
    /bin
    usr/bin/
    /usr/local/bin
    /some\ horrible thing
    /even 
    new lines

    Les options utilisées sont -d: qui définit le délimiteur d'entrée à : , -f 1- ce qui signifie imprimer tous les champs (du 1er à la fin) et --output-delimiter=$'\n' qui définit le, eh bien, le délimiteur de sortie. Le site $'\n' es Cotation ANSI C et est un moyen d'imprimer un caractère de nouvelle ligne dans le Shell.

Dans tous les exemples ci-dessus, j'utilise la fonction de bash (et d'autres shells) ici la chaîne ( <<< ) pour transmettre une chaîne de caractères en entrée d'un programme. Ainsi, command <<<"foo" est équivalent à echo -n "foo" | command . Notez que je cite toujours "$PATH" Sans les guillemets, le Shell aurait mangé le caractère de nouvelle ligne.


@7stud a donné une autre approche dans les commentaires c'est juste trop bon pour ne pas l'inclure :

$ perl -0x3a -l012 -pe '' <<<"$PATH"

C'est ce que l'on appelle le golf . Le site -0 spécifie le séparateur d'enregistrement d'entrée sous la forme d'un nombre octal ou hexadécimal. C'est ce qui définit une "ligne" et sa valeur par défaut est \n un caractère de nouvelle ligne. Ici, nous le définissons comme un : qui est x3a en hexagone (essayez printf '\x3a\n' ). Le site -l fait trois choses. Premièrement, il supprime le séparateur d'enregistrement d'entrée ( $/ ) à la fin de chaque ligne, ce qui a pour effet de supprimer l'élément : et deuxièmement, il définit le séparateur d'enregistrement de sortie ( $\ ) à la valeur octale ou hexagonale qui lui est donnée ( 012 es \n ). Si $\ est définie, elle est ajoutée à la fin de chaque fichier print ce qui entraînera l'ajout d'un saut de ligne à chaque appel print .

El -pe sera p rint chaque ligne d'entrée après avoir appliqué le script donné par -e . Ici, il n'y a pas de script car tout le travail est fait par les drapeaux d'option comme décrit ci-dessus !

4voto

Avinash Raj Points 72686

Par le biais de l'awk.

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

Grâce à Python.

$ echo $PATH | python3 -c 'import fileinput
for line in fileinput.input():
    for i in line.split(":"):
        print(i)'

Notez que l'indentation est très importante en Python.

4voto

Kaz Wolfe Points 32777

Nous avons besoin de plus de Java !

public class GetPathByLine {
    public static void main(String[] args) {
        for (String p : System.getenv("PATH").split(":")) {
            System.out.println(p);
        }
    }
}

Sauvegardez ceci sur GetPathByLine.java et compiler en utilisant :

javac GetPathByLine.java

Fonctionne avec :

java GetPathByLine

[17:06:55][kazwolfe@BlackHawk]
> ~ $ cat GetPathByLine.java 
public class GetPathByLine {
    public static void main(String[] args) {
        for (String p : System.getenv("PATH").split(":")) {
            System.out.println(p);
        }
    }
}
[17:06:58][kazwolfe@BlackHawk]
> ~ $ javac GetPathByLine.java 
[17:07:02][kazwolfe@BlackHawk]
> ~ $ java GetPathByLine 
/usr/local/sbin
/usr/local/bin
/usr/sbin
/usr/bin
/sbin
/bin
/usr/games
/usr/local/games
/snap/bin

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X