Come manipolo gli elementi $ PATH negli script di shell?
-
07-07-2019 - |
Domanda
Esiste un modo idiomatico di rimuovere elementi da variabili shell tipo PATH?
Questo è quello che voglio prendere
PATH=/home/joe/bin:/usr/local/bin:/usr/bin:/bin:/path/to/app/bin:.
e rimuovi o sostituisci il / path / to / app / bin
senza ostruire il resto della variabile. Punti extra per avermi permesso di mettere nuovi elementi in posizioni arbitrarie. Il target sarà riconoscibile da una stringa ben definita e potrebbe verificarsi in qualsiasi punto dell'elenco.
So di averlo visto fatto e probabilmente posso mettere insieme qualcosa da solo, ma sto cercando un approccio piacevole. Portabilità e standardizzazione un vantaggio.
Uso bash, ma anche gli esempi sono i benvenuti nella tua shell preferita.
Il contesto qui è quello di dover passare convenientemente tra più versioni (una per fare analisi, un'altra per lavorare sul framework) di un ampio pacchetto di analisi scientifica che produce una dozzina di eseguibili, ha i dati racchiusi nel filesystem e usa la variabile d'ambiente per aiutare a trovare tutte queste cose. Vorrei scrivere uno script che seleziona una versione e devo poter rimuovere gli elementi $ PATH
relativi alla versione attualmente attiva e sostituirli con gli stessi elementi relativi alla nuova versione.
Questo è legato al problema di prevenire elementi $ PATH
ripetuti quando si rieseguono script di login e simili.
- Domanda simile precedente: Come evitare di duplicare la variabile del percorso in csh
- Domanda successiva successiva: Qual è il modo più elegante per rimuovere un percorso dalla variabile $ PATH in Bash?
Soluzione
Indirizzare la soluzione proposta da dmckee:
- Mentre alcune versioni di Bash possono consentire trattini nei nomi delle funzioni, altre (MacOS X) no.
- Non vedo la necessità di utilizzare return immediatamente prima della fine della funzione.
- Non vedo la necessità di tutti i punti e virgola.
- Non vedo perché hai esportato un valore percorso elemento per modello. Pensa a
export
come equivalente all'impostazione (o persino alla creazione) di una variabile globale - qualcosa da evitare quando possibile. - Non sono sicuro di cosa ti aspetti che faccia <
sostituisci percorso PATH $ PERCORSO / usr
, ma non fa ciò che mi aspetto.
Prendi in considerazione un valore PERCORSO che inizia con:
.
/Users/jleffler/bin
/usr/local/postgresql/bin
/usr/local/mysql/bin
/Users/jleffler/perl/v5.10.0/bin
/usr/local/bin
/usr/bin
/bin
/sw/bin
/usr/sbin
/sbin
Il risultato che ho ottenuto (da ' replace-path PATH $ PATH / usr
') è:
.
/Users/jleffler/bin
/local/postgresql/bin
/local/mysql/bin
/Users/jleffler/perl/v5.10.0/bin
/local/bin
/bin
/bin
/sw/bin
/sbin
/sbin
Mi sarei aspettato di recuperare il mio percorso originale poiché / usr non appare come un elemento (completo) del percorso, solo come parte di un elemento del percorso.
Questo può essere risolto in replace-path
modificando uno dei comandi sed
:
export $path=$(echo -n $list | tr ":" "\n" | sed "s:^$removestr\$:$replacestr:" |
tr "\n" ":" | sed "s|::|:|g")
Ho usato ':' invece di '|' separare parti del sostituto dal '|' potrebbe (in teoria) apparire in una componente del percorso, mentre per definizione di PERCORSO, un colon non può. Osservo che il secondo sed
potrebbe eliminare l'attuale directory dal mezzo di un PERCORSO. Cioè, un valore legittimo (sebbene perverso) di PATH potrebbe essere:
PATH=/bin::/usr/local/bin
Dopo l'elaborazione, la directory corrente non sarà più sul PERCORSO.
Una modifica simile per ancorare la corrispondenza è appropriata in path-element-by-pattern
:
export $target=$(echo -n $list | tr ":" "\n" | grep -m 1 "^$pat\# path_tools.bash
#
# A set of tools for manipulating ":" separated lists like the
# canonical $PATH variable.
#
# /bin/sh compatibility can probably be regained by replacing $( )
# style command expansion with ` ` style
###############################################################################
# Usage:
#
# To remove a path:
# replace_path PATH $PATH /exact/path/to/remove
# replace_path_pattern PATH $PATH <grep pattern for target path>
#
# To replace a path:
# replace_path PATH $PATH /exact/path/to/remove /replacement/path
# replace_path_pattern PATH $PATH <target pattern> /replacement/path
#
###############################################################################
# Remove or replace an element of $1
#
# $1 name of the shell variable to set (e.g. PATH)
# $2 a ":" delimited list to work from (e.g. $PATH)
# $3 the precise string to be removed/replaced
# $4 the replacement string (use "" for removal)
function replace_path () {
path=$1
list=$2
remove=$3
replace=$4 # Allowed to be empty or unset
export $path=$(echo "$list" | tr ":" "\n" | sed "s:^$remove\$:$replace:" |
tr "\n" ":" | sed 's|:$||')
}
# Remove or replace an element of $1
#
# $1 name of the shell variable to set (e.g. PATH)
# $2 a ":" delimited list to work from (e.g. $PATH)
# $3 a grep pattern identifying the element to be removed/replaced
# $4 the replacement string (use "" for removal)
function replace_path_pattern () {
path=$1
list=$2
removepat=$3
replacestr=$4 # Allowed to be empty or unset
removestr=$(echo "$list" | tr ":" "\n" | grep -m 1 "^$removepat\#!/usr/bin/perl -w
#
# "@(#)$Id: echopath.pl,v 1.7 1998/09/15 03:16:36 jleffler Exp echo
xpath=$PATH
replace_path xpath $xpath /usr
echopath $xpath
echo
xpath=$PATH
replace_path_pattern xpath $xpath /usr/bin /work/bin
echopath xpath
echo
xpath=$PATH
replace_path_pattern xpath $xpath "/usr/.*/bin" /work/bin
echopath xpath
quot;
#
# Print the components of a PATH variable one per line.
# If there are no colons in the arguments, assume that they are
# the names of environment variables.
@ARGV = $ENV{PATH} unless @ARGV;
foreach $arg (@ARGV)
{
$var = $arg;
$var = $ENV{$arg} if $arg =~ /^[A-Za-z_][A-Za-z_0-9]*$/;
$var = $arg unless $var;
@lst = split /:/, $var;
foreach $val (@lst)
{
print "$val\n";
}
}
quot;)
replace_path "$path" "$list" "$removestr" "$replacestr"
}
quot;)
Prendo atto che grep -m 1
non è standard (è un'estensione GNU, disponibile anche su MacOS X). E, in effetti, anche l'opzione -n
per echo
non è standard; staresti meglio semplicemente cancellando i due punti finali aggiunti in virtù della conversione della nuova riga dall'eco in due punti. Poiché il percorso elemento per modello viene usato una sola volta, ha effetti collaterali indesiderati (blocca qualsiasi variabile esportata preesistente chiamata $ removestr
), può essere sostituita sensibilmente dal suo corpo. Questo, insieme a un uso più liberale delle virgolette per evitare problemi con spazi o l'espansione indesiderata dei nomi di file, porta a:
.
/Users/jleffler/bin
/usr/local/postgresql/bin
/usr/local/mysql/bin
/Users/jleffler/perl/v5.10.0/bin
/usr/local/bin
/usr/bin
/bin
/sw/bin
/usr/sbin
/sbin
.
/Users/jleffler/bin
/usr/local/postgresql/bin
/usr/local/mysql/bin
/Users/jleffler/perl/v5.10.0/bin
/usr/local/bin
/work/bin
/bin
/sw/bin
/usr/sbin
/sbin
.
/Users/jleffler/bin
/work/bin
/usr/local/mysql/bin
/Users/jleffler/perl/v5.10.0/bin
/usr/local/bin
/usr/bin
/bin
/sw/bin
/usr/sbin
/sbin
Ho uno script Perl chiamato echopath
che trovo utile quando eseguo il debug di problemi con variabili tipo PATH:
replace_path PATH /usr/bin /work/bin
Quando eseguo la soluzione modificata sul codice di test riportato di seguito:
list=$(eval echo '
L'output è:
# path_tools.bash
#
# A set of tools for manipulating ":" separated lists like the
# canonical $PATH variable.
#
# /bin/sh compatibility can probably be regained by replacing $( )
# style command expansion with ` ` style
###############################################################################
# Usage:
#
# To remove a path:
# replace_path PATH /exact/path/to/remove
# replace_path_pattern PATH <grep pattern for target path>
#
# To replace a path:
# replace_path PATH /exact/path/to/remove /replacement/path
# replace_path_pattern PATH <target pattern> /replacement/path
#
###############################################################################
# Remove or replace an element of $1
#
# $1 name of the shell variable to set (e.g. PATH)
# $2 the precise string to be removed/replaced
# $3 the replacement string (use "" for removal)
function replace_path () {
path=$1
list=$(eval echo '
Questo mi sembra corretto, almeno per la mia definizione di quale sia il problema.
Prendo atto che echopath LD_LIBRARY_PATH
valuta $ LD_LIBRARY_PATH
. Sarebbe bello se le tue funzioni fossero in grado di farlo, quindi l'utente potrebbe digitare:
echo
xpath=$PATH
replace_path xpath /usr
echopath xpath
echo
xpath=$PATH
replace_path_pattern xpath /usr/bin /work/bin
echopath xpath
echo
xpath=$PATH
replace_path_pattern xpath "/usr/.*/bin" /work/bin
echopath xpath
Questo può essere fatto usando:
<*>
Questo porta a questa revisione del codice:
<*>
Ora funziona anche il seguente test rivisto:
<*>
Produce lo stesso output di prima.
$path)
L'output è:
<*>
Questo mi sembra corretto, almeno per la mia definizione di quale sia il problema.
Prendo atto che echopath LD_LIBRARY_PATH
valuta $ LD_LIBRARY_PATH
. Sarebbe bello se le tue funzioni fossero in grado di farlo, quindi l'utente potrebbe digitare:
<*>
Questo può essere fatto usando:
<*>
Questo porta a questa revisione del codice:
<*>
Ora funziona anche il seguente test rivisto:
<*>
Produce lo stesso output di prima.
$path)
remove=$2
replace=$3 # Allowed to be empty or unset
export $path=$(echo "$list" | tr ":" "\n" | sed "s:^$remove\$:$replace:" |
tr "\n" ":" | sed 's|:$||')
}
# Remove or replace an element of $1
#
# $1 name of the shell variable to set (e.g. PATH)
# $2 a grep pattern identifying the element to be removed/replaced
# $3 the replacement string (use "" for removal)
function replace_path_pattern () {
path=$1
list=$(eval echo '
Questo mi sembra corretto, almeno per la mia definizione di quale sia il problema.
Prendo atto che echopath LD_LIBRARY_PATH
valuta $ LD_LIBRARY_PATH
. Sarebbe bello se le tue funzioni fossero in grado di farlo, quindi l'utente potrebbe digitare:
<*>
Questo può essere fatto usando:
<*>
Questo porta a questa revisione del codice:
<*>
Ora funziona anche il seguente test rivisto:
<*>
Produce lo stesso output di prima.
$path)
L'output è:
<*>Questo mi sembra corretto, almeno per la mia definizione di quale sia il problema.
Prendo atto che echopath LD_LIBRARY_PATH
valuta $ LD_LIBRARY_PATH
. Sarebbe bello se le tue funzioni fossero in grado di farlo, quindi l'utente potrebbe digitare:
Questo può essere fatto usando:
<*>Questo porta a questa revisione del codice:
<*>Ora funziona anche il seguente test rivisto:
<*>Produce lo stesso output di prima.
$path) removepat=$2 replacestr=$3 # Allowed to be empty or unset removestr=$(echo "$list" | tr ":" "\n" | grep -m 1 "^$removepat\<*>quot;) replace_path "$path" "$removestr" "$replacestr" }Questo mi sembra corretto, almeno per la mia definizione di quale sia il problema.
Prendo atto che echopath LD_LIBRARY_PATH
valuta $ LD_LIBRARY_PATH
. Sarebbe bello se le tue funzioni fossero in grado di farlo, quindi l'utente potrebbe digitare:
Questo può essere fatto usando:
<*>Questo porta a questa revisione del codice:
<*>Ora funziona anche il seguente test rivisto:
<*>Produce lo stesso output di prima.
$path)L'output è:
<*>Questo mi sembra corretto, almeno per la mia definizione di quale sia il problema.
Prendo atto che echopath LD_LIBRARY_PATH
valuta $ LD_LIBRARY_PATH
. Sarebbe bello se le tue funzioni fossero in grado di farlo, quindi l'utente potrebbe digitare:
Questo può essere fatto usando:
<*>Questo porta a questa revisione del codice:
<*>Ora funziona anche il seguente test rivisto:
<*>Produce lo stesso output di prima.
Altri suggerimenti
Ripubblicando la mia risposta a Qual è il modo più elegante per rimuovere un percorso dalla variabile $ PATH in Bash? :
#!/bin/bash
IFS=:
# convert it to an array
t=($PATH)
unset IFS
# perform any array operations to remove elements from the array
t=(${t[@]%%*usr*})
IFS=:
# output the new array
echo "${t[*]}"
o one-liner:
PATH=$(IFS=':';t=($PATH);unset IFS;t=(${t[@]%%*usr*});IFS=':';echo "${t[*]}");
Per cancellare un elemento puoi usare sed:
#!/bin/bash
NEW_PATH=$(echo -n $PATH | tr ":" "\n" | sed "/foo/d" | tr "\n" ":")
export PATH=$NEW_PATH
eliminerà i percorsi che contengono " foo " dal percorso.
Puoi anche usare sed per inserire una nuova riga prima o dopo una data riga.
Modifica: puoi rimuovere i duplicati eseguendo il piping tramite sort e uniq:
echo -n $PATH | tr ":" "\n" | sort | uniq -c | sed -n "/ 1 / s/.*1 \(.*\)/\1/p" | sed "/foo/d" | tr "\n" ":"
Esistono un paio di programmi pertinenti nelle risposte a " Come evitare di duplicare la variabile del percorso in csh " ;. Si concentrano maggiormente sull'assicurare che non vi siano elementi ripetuti, ma lo script che fornisco può essere usato come:
export PATH=$(clnpath $head_dirs:$PATH:$tail_dirs $remove_dirs)
Supponendo che tu abbia una o più directory in $ head_dirs e una o più directory in $ tail_dirs e una o più directory in $ remove_dirs, quindi usa la shell per concatenare le parti head, current e tail in un valore enorme, e quindi rimuove ciascuna delle directory elencate in $ remove_dirs dal risultato (non un errore se non esistono), oltre a eliminare le seconde e successive occorrenze di qualsiasi directory nel percorso.
Non si tratta di mettere i componenti del percorso in una posizione specifica (tranne all'inizio o alla fine, e solo indirettamente). Notativamente, specificare dove si desidera aggiungere il nuovo elemento o quale elemento si desidera sostituire è disordinato.
Solo una nota che bash stesso può fare ricerca e sostituire. Può fare tutte le normali opzioni "una volta o tutte", in casi sensibili [in] che ti aspetteresti.
Dalla pagina man:
$ {parametro / modello / stringa}
Il pattern viene espanso per produrre un pattern proprio come nell'espansione del nome percorso. Il parametro viene espanso e la corrispondenza più lunga del modello rispetto al suo valore viene sostituita con stringa. Se Ipattern inizia con /, tutte le corrispondenze del modello vengono sostituite con stringa. Normalmente viene sostituita solo la prima partita. Se il modello inizia con #, deve corrispondere all'inizio del valore espanso del parametro. Se il modello inizia con%, deve corrispondere alla fine del valore espanso del parametro. Se la stringa è nulla, le corrispondenze del modello vengono eliminate e il modello / seguente può essere omesso. Se il parametro è @ o *, l'operazione di sostituzione viene applicata a turno a ciascun parametro posizionale e l'espansione è l'elenco risultante. Se il parametro è una variabile di matrice sottoscritta con @ o *, l'operazione di sostituzione viene applicata a turno a ciascun membro dell'array e l'espansione è l'elenco risultante.
Puoi anche dividere i campi impostando $ IFS (separatore dei campi di input) sul delimitatore desiderato.
OK, grazie a tutti i rispondenti. Ho preparato una versione incapsulata della risposta di Florin. Il primo passaggio è simile al seguente:
# path_tools.bash
#
# A set of tools for manipulating ":" separated lists like the
# canonical $PATH variable.
#
# /bin/sh compatibility can probably be regained by replacing $( )
# style command expansion with ` ` style
###############################################################################
# Usage:
#
# To remove a path:
# replace-path PATH $PATH /exact/path/to/remove
# replace-path-pattern PATH $PATH <grep pattern for target path>
#
# To replace a path:
# replace-path PATH $PATH /exact/path/to/remove /replacement/path
# replace-path-pattern PATH $PATH <target pattern> /replacement/path
#
###############################################################################
# Finds the _first_ list element matching $2
#
# $1 name of a shell variable to be set
# $2 name of a variable with a path-like structure
# $3 a grep pattern to match the desired element of $1
function path-element-by-pattern (){
target=$1;
list=$2;
pat=$3;
export $target=$(echo -n $list | tr ":" "\n" | grep -m 1 $pat);
return
}
# Removes or replaces an element of $1
#
# $1 name of the shell variable to set (i.e. PATH)
# $2 a ":" delimited list to work from (i.e. $PATH)
# $2 the precise string to be removed/replaced
# $3 the replacement string (use "" for removal)
function replace-path () {
path=$1;
list=$2;
removestr=$3;
replacestr=$4; # Allowed to be ""
export $path=$(echo -n $list | tr ":" "\n" | sed "s|$removestr|$replacestr|" | tr "\n" ":" | sed "s|::|:|g");
unset removestr
return
}
# Removes or replaces an element of $1
#
# $1 name of the shell variable to set (i.e. PATH)
# $2 a ":" delimited list to work from (i.e. $PATH)
# $2 a grep pattern identifying the element to be removed/replaced
# $3 the replacement string (use "" for removal)
function replace-path-pattern () {
path=$1;
list=$2;
removepat=$3;
replacestr=$4; # Allowed to be ""
path-element-by-pattern removestr $list $removepat;
replace-path $path $list $removestr $replacestr;
}
Ho ancora bisogno di intercettare errori in tutte le funzioni, e probabilmente dovrei attaccare una soluzione a percorso ripetuto mentre ci sono.
Lo usi facendo un . /include/path/path_tools.bash
nello script di lavoro e invocazione delle funzioni replace-path *
.
Sono ancora aperto a risposte nuove e / o migliori.
È facile usare awk.
Sostituire
{
for(i=1;i<=NF;i++)
if($i == REM)
if(REP)
print REP;
else
continue;
else
print $i;
}
Avvialo usando
function path_repl {
echo $PATH | awk -F: -f rem.awk REM="$1" REP="$2" | paste -sd:
}
$ echo $PATH
/bin:/usr/bin:/home/js/usr/bin
$ path_repl /bin /baz
/baz:/usr/bin:/home/js/usr/bin
$ path_repl /bin
/usr/bin:/home/js/usr/bin
Append
Inserisce nella posizione data. Per impostazione predefinita, viene aggiunto alla fine.
{
if(IDX < 1) IDX = NF + IDX + 1
for(i = 1; i <= NF; i++) {
if(IDX == i)
print REP
print $i
}
if(IDX == NF + 1)
print REP
}
Avvialo usando
function path_app {
echo $PATH | awk -F: -f app.awk REP="$1" IDX="$2" | paste -sd:
}
$ echo $PATH
/bin:/usr/bin:/home/js/usr/bin
$ path_app /baz 0
/bin:/usr/bin:/home/js/usr/bin:/baz
$ path_app /baz -1
/bin:/usr/bin:/baz:/home/js/usr/bin
$ path_app /baz 1
/baz:/bin:/usr/bin:/home/js/usr/bin
Rimuovi duplicati
Questo mantiene le prime occorrenze.
{
for(i = 1; i <= NF; i++) {
if(!used[$i]) {
print $i
used[$i] = 1
}
}
}
Inizia così:
echo $PATH | awk -F: -f rem_dup.awk | paste -sd:
Convalida se esistono tutti gli elementi
Di seguito verrà stampato un messaggio di errore per tutte le voci che non sono presenti nel filesystem e restituirà un valore diverso da zero.
echo -n $PATH | xargs -d: stat -c %n
Per controllare semplicemente se tutti gli elementi sono percorsi e ottenere un codice di ritorno, puoi anche utilizzare test
:
echo -n $PATH | xargs -d: -n1 test -d
supponi
echo $PATH
/usr/lib/jvm/java-1.6.0/bin:lib/jvm/java-1.6.0/bin/:/lib/jvm/java-1.6.0/bin/:/usr/lib/qt-3.3/bin:/usr/lib/ccache:/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin:/home/tvnadeesh/bin
Se vuoi rimuovere /lib/jvm/java-1.6.0/bin/ fai come di seguito
export PATH=$(echo $PATH | sed 's/\/lib\/jvm\/java-1.6.0\/bin\/://g')
sed
prenderà l'input da echo $ PATH
e sostituirà /lib/jvm/java-1.6.0/bin/: con vuoto
in questo modo è possibile rimuovere
- L'ordine del PERCORSO non è disturbato
- Gestisce casi angolari come percorso vuoto, spazio nel percorso con grazia
- La corrispondenza parziale di dir non fornisce falsi positivi
- Tratta il percorso in testa e in coda al PERCORSO in modo corretto. No : immondizia e simili.
Di 'che hai / Foo: / qualche / percorso: / qualche / percorso / dir1: / qualche / percorso / dir2: / bar e vuoi sostituire / Some / percorso Quindi sostituisce correttamente " / some / path " ma lascia " / some / path / dir1 " o " / some / path / dir2 " ;, come quello che ti aspetteresti.
function __path_add(){
if [ -d "$1" ] ; then
local D=":${PATH}:";
[ "${D/:$1:/:}" == "$D" ] && PATH="$PATH:$1";
PATH="${PATH/#:/}";
export PATH="${PATH/%:/}";
fi
}
function __path_remove(){
local D=":${PATH}:";
[ "${D/:$1:/:}" != "$D" ] && PATH="${D/:$1:/:}";
PATH="${PATH/#:/}";
export PATH="${PATH/%:/}";
}
# Just for the shake of completeness
function __path_replace(){
if [ -d "$2" ] ; then
local D=":${PATH}:";
if [ "${D/:$1:/:}" != "$D" ] ; then
PATH="${D/:$1:/:$2:}";
PATH="${PATH/#:/}";
export PATH="${PATH/%:/}";
fi
fi
}
Post correlato Qual è il modo più elegante per rimuovere un percorso dalla variabile $ PATH in Bash?
Preferisco usare il rubino a artisti del calibro di awk / sed / foo in questi giorni, quindi ecco il mio approccio per gestire i duplicati,
# add it to the path
PATH=~/bin/:$PATH:~/bin
export PATH=$(ruby -e 'puts ENV["PATH"].split(/:/).uniq.join(":")')
crea una funzione per il riutilizzo,
mungepath() {
export PATH=$(ruby -e 'puts ENV["PATH"].split(/:/).uniq.join(":")')
}
Hash, array e stringhe in un liner rubino :)
La prima cosa che mi viene in mente di cambiare solo parte di una stringa è una sostituzione sed.
Esempio: se echo $ PATH = > & Quot; / usr / pkg / bin: / usr / bin: / bin: / usr / pkg / giochi: / usr / pkg / X11R6 / bin " quindi per cambiare " / usr / bin " a " / usr / local / bin " potrebbe essere fatto in questo modo:
## produce file di output standard
## the " = " viene utilizzato il carattere anziché la barra (" / ") poiché sarebbe disordinato, # Il carattere di citazione alternativo dovrebbe essere improbabile nel PERCORSO
## il carattere separatore di percorso ": " viene rimosso e aggiunto nuovamente qui, # potrebbe desiderare un punto in più dopo l'ultimo percorso
echo $ PATH | sed '= / usr / bin: = / usr / local / bin: ='
Questa soluzione sostituisce un intero elemento path quindi potrebbe essere ridondante se new-element è simile.
Se i nuovi PATH non sono dinamici ma sempre all'interno di un insieme costante, è possibile salvare quelli in una variabile e assegnarli secondo necessità:
PATH = $ TEMP_PATH_1; # comandi ...; \ n PATH = $ TEMP_PATH_2; # comandi ecc ...;
Potrebbe non essere quello che stavi pensando. alcuni dei comandi rilevanti su bash / unix sarebbero:
pushd popd CD ls # forse l -1A per singola colonna; trova grep quale # potrebbe confermare che il file è da dove pensi che sia venuto; ENV Tipo
..e tutto il resto ha alcuni attinenti a PATH o directory in generale. La parte che modifica il testo può essere eseguita in vari modi!
Qualunque soluzione scelta avrebbe 4 parti:
1) recupera il percorso così com'è 2) decodifica il percorso per trovare la parte che necessita di modifiche 3) determinare quali cambiamenti sono necessari / integrare tali cambiamenti 4) validazione / integrazione finale / impostazione della variabile
In linea con la risposta di dj_segfault , lo faccio negli script che aggiungono / antepongono variabili di ambiente che potrebbero essere eseguite più volte :
ld_library_path=${ORACLE_HOME}/lib
LD_LIBRARY_PATH=${LD_LIBRARY_PATH//${ld_library_path}?(:)/}
export LD_LIBRARY_PATH=${ld_library_path}${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}}
Usare questa stessa tecnica per rimuovere, sostituire o manipolare le voci in PATH è banale dato la corrispondenza del modello simile all'espansione del nome file e il supporto dell'elenco dei modelli dell'espansione dei parametri della shell.