2009-09-08 10 views

risposta

3

Qualcosa di veramente semplice e ingenuo:

echo "$PATH"|grep -q whatever && echo "found it" 

Dove tutto ciò è quello che stai cercando. Invece di && è possibile inserire $? in una variabile o utilizzare un'istruzione if corretta.

Limitazioni includono:

  • È possibile che questo corrisponderà stringhe dei percorsi più grandi (provate corrispondenza su "bin" e sarà probabilmente trovarlo, nonostante il fatto che "bin" non è nel percorso,/bin e/usr/bin sono)
  • Quanto sopra non si espanderà automaticamente scorciatoie come ~

o utilizzando un perl one-liner:

perl -e 'exit(!(grep(m{^/usr/bin$},split(":", $ENV{PATH}))) > 0)' && echo "found it" 

Questo ha ancora il limite che non farà alcuna espansione della shell, ma non fallisce se una sottostringa corrisponde. (Il precedente corrisponde a "/usr/bin", nel caso in cui non fosse chiaro).

+1

Corrispondenza con inizio/fine riga e due punti come nella risposta JasonWoof si prende cura della limitazione della sottostringa. L'espansione delle tilde non è un problema comune, dal momento che molte persone permettono che venga espansa quando viene assegnata (ad esempio 'PATH =" ~/bin: $ PATH "'), ma può essere gestita con una sostituzione, se necessario. – Cascabel

+2

Bello, qualcuno ha downvoted questo dopo 3,5 anni. E non ha lasciato un commento. Noioso. –

+0

Sto utilizzando la soluzione grep che avvolge il pattern con i due punti. – elias

102

L'utilizzo di grep è eccessivo e può causare problemi se si sta cercando qualcosa che include i metacaratteri RE. Questo problema può essere risolto perfettamente con incorporato [[ comando di bash:

if [[ ":$PATH:" == *":$HOME/bin:"* ]]; then 
    echo "Your path is correctly set" 
else 
    echo "Your path is missing ~/bin, you might want to add it." 
fi 

Nota che l'aggiunta di due punti prima che sia l'espansione delle $ PATH e il percorso per cercare di risolvere il problema sottostringa partita; la doppia citazione del percorso evita problemi con i metacaratteri.

+4

Se '$ HOME/bin' è all'inizio o alla fine di' $ PATH', allora non è probabile che vi siano due punti a ciascuna estremità. –

+8

Non sono sicuro di capire la tua obiezione. Ad esempio, se $ PATH è/usr/bin:/bin:/usr/sbin:/sbin:/home/fred/bin, quindi ":/usr/bin:/bin:/usr/sbin:/sbin:/home/fred/bin: "corrisponderà a *":/home/fred/bin: "* bene. –

+6

Hai ragione. Non ero riuscito a vedere il ruolo dei due punti attorno a "$ PATH". Scusate. –

10

Ecco come farlo senza grep:

if [[ $PATH == ?(*:)$HOME/bin?(:*) ]] 

La chiave qui è quello di rendere i due punti e caratteri jolly opzionale utilizzando il ?() costrutto. Non ci dovrebbe essere alcun problema con metacaratteri in questa forma, ma se si desidera includere citazioni questo è dove vanno:

if [[ "$PATH" == ?(*:)"$HOME/bin"?(:*) ]] 

Questo è un altro modo per farlo utilizzando l'operatore match (=~) quindi la sintassi è più simile grep 's:

if [[ "$PATH" =~ (^|:)"${HOME}/bin"(:|$) ]] 
+0

Il '? (: *)' È un pattern [extended glob] (https://mywiki.wooledge.org/glob#extglob) che deve essere esplicitamente abilitato separatamente sulla maggior parte delle piattaforme ('shopt -s extglob'). – tripleee

0

$PATH è una lista di stringhe separate da : che descrivono una lista di directory. Una directory è un elenco di stringhe separate da /. Due stringhe diverse possono puntare alla stessa directory (come $HOME e ~ o /usr/local/bin e /usr/local/bin/). Quindi dobbiamo fissare le regole di ciò che vogliamo confrontare/controllare. Suggerisco di confrontare/controllare l'intero stringhe, e non le directory fisiche, ma rimuovere il duplicato e il trailing /.

Prima duplicare Rimuovere e finali / da $PATH:

 
echo $PATH | tr -s/| sed 's/\/:/:/g;s/:/\n/g' 

Ora supponiamo $d contiene la directory che si desidera controllare. Quindi passare il comando precedente per verificare $d in $PATH.

 
echo $PATH | tr -s/| sed 's/\/:/:/g;s/:/\n/g' | grep -q "^$d$" || echo "missing $d" 
0

ho scritto la seguente funzione di shell per segnalare se una directory è elencato nella corrente PATH. Questa funzione è compatibile con POSIX e funzionerà in shell compatibili come Dash e Bash (senza fare affidamento sulle funzionalità specifiche di Bash).

Include funzionalità per convertire un percorso relativo in un percorso assoluto. Utilizza le utilità readlink o realpath per questo ma questi strumenti non sono necessari se la directory fornita non ha .. o altri collegamenti come componenti del suo percorso. Oltre a questo, la funzione non richiede alcun programma esterno alla shell.

# Check that the specified directory exists – and is in the PATH. 
is_dir_in_path() 
{ 
    if [ -z "${1:-}" ]; then 
    printf "The path to a directory must be provided as an argument.\n" >&2 
    return 1 
    fi 

    # Check that the specified path is a directory that exists. 
    if ! [ -d "$1" ]; then 
    printf "Error: ‘%s’ is not a directory.\n" "$1" >&2 
    return 1 
    fi 

    # Use absolute path for the directory if a relative path was specified. 
    if command -v readlink >/dev/null ; then 
    dir="$(readlink -f "$1")" 
    elif command -v realpath >/dev/null ; then 
    dir="$(realpath "$1")" 
    else 
    case "$1" in 
     /*) 
     # The path of the provided directory is already absolute. 
     dir="$1" 
     ;; 
     *) 
     # Prepend the path of the current directory. 
     dir="$PWD/$1" 
     ;; 
    esac 
    printf "Warning: neither ‘readlink’ nor ‘realpath’ are available.\n" 
    printf "Ensure that the specified directory does not contain ‘..’ in its path.\n" 
    fi 

    # Check that dir is in the user’s PATH. 
    case ":$PATH:" in 
    *:"$dir":*) 
     printf "‘%s’ is in the PATH.\n" "$dir" 
     return 0 
     ;; 
    *) 
     printf "‘%s’ is not in the PATH.\n" "$dir" 
     return 1 
     ;; 
    esac 
} 

La parte utilizzando :$PATH: assicura che il modello corrisponde anche se il percorso desiderato è la prima o l'ultima entrata nel PATH. Questo trucco intelligente si basa su this answer by Glenn Jackman on Unix & Linux.

0

Per questo non è assolutamente necessario utilizzare utilità esterne come grep. Ecco cosa ho usato, che dovrebbe essere trasferito a versioni precedenti della shell Bourne.

case :$PATH: # notice colons around the value 
    in *:$HOME/bin:*) ;; # do nothing, it's there 
    *) echo "$HOME/bin not in $PATH" >&2;; 
esac 
Problemi correlati