Question

Existe-t-il un moyen idiomatique de supprimer des éléments de variables de shell de type PATH?

C'est ce que je veux prendre

PATH=/home/joe/bin:/usr/local/bin:/usr/bin:/bin:/path/to/app/bin:.

et supprimez ou remplacez le / chemin / vers / app / bin sans masquer le reste de la variable. Des points supplémentaires pour me permettre de mettre de nouveaux éléments dans des positions arbitraires. La cible sera reconnaissable par une chaîne bien définie et pourra se trouver n'importe où dans la liste.

Je sais que j’ai vu cela se faire et que je peux probablement bricoler quelque chose tout seul, mais je cherche une bonne approche. Portabilité et normalisation un plus.

J'utilise bash, mais les exemples sont également les bienvenus dans votre shell favori.

Le contexte est celui de la nécessité de basculer facilement entre plusieurs versions (une pour effectuer une analyse, une autre pour travailler sur le framework) d'un grand logiciel d'analyse scientifique qui produit une douzaine d'exécutables, contient des données stockées autour du système de fichiers et utilise la variable d'environnement pour aider à trouver tout ça. Je souhaite écrire un script qui sélectionne une version et doit pouvoir supprimer les éléments $ PATH relatifs à la version actuellement active et les remplacer par les mêmes éléments relatifs à la nouvelle version.

Ceci est lié au problème d'empêcher la répétition d'éléments $ PATH lors de la réexécution de scripts de connexion, etc.>

Était-ce utile?

La solution

Traitement de la solution proposée par dmckee:

  1. Alors que certaines versions de Bash peuvent autoriser des traits d'union dans les noms de fonction, d'autres (MacOS X) ne le font pas.
  2. Je ne vois pas la nécessité d'utiliser return immédiatement avant la fin de la fonction.
  3. Je ne vois pas la nécessité de tous les points-virgules.
  4. Je ne vois pas pourquoi vous avez exporté une valeur chemin par élément. Pensez à export comme équivalent à la définition (ou même la création) d'une variable globale - à éviter autant que possible.
  5. Je ne suis pas sûr de ce que vous attendez que chemin de remplacement remplace PATH $ PATH / usr , mais il ne fait pas ce que j'attendais.

Prenons une valeur PATH qui commence par contenir:

.
/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

Le résultat que j'ai obtenu (à partir de ' remplacement-chemin PATH $ PATH / usr ') est:

.
/Users/jleffler/bin
/local/postgresql/bin
/local/mysql/bin
/Users/jleffler/perl/v5.10.0/bin
/local/bin
/bin
/bin
/sw/bin
/sbin
/sbin

Je me serais attendu à retrouver mon chemin d'origine car / usr n'apparaît pas en tant qu'élément de chemin complet, mais uniquement en tant qu'élément d'un élément de chemin.

Ceci peut être corrigé dans replace-path en modifiant l'une des commandes sed :

export $path=$(echo -n $list | tr ":" "\n" | sed "s:^$removestr\$:$replacestr:" |
               tr "\n" ":" | sed "s|::|:|g")

J'ai utilisé ':' au lieu de '|' séparer des parties du substitut puisque '|' pourrait (en théorie) apparaître dans un composant de chemin, alors que par définition, PATH, un colon ne peut pas Je remarque que le second sed pourrait éliminer le répertoire actuel du milieu d'un PATH. C'est-à-dire qu'une valeur légitime (bien que perverse) de PATH pourrait être:

PATH=/bin::/usr/local/bin

Après le traitement, le répertoire en cours ne serait plus dans le PATH.

Une modification similaire visant à ancrer la correspondance est appropriée dans motif-élément-par-motif :

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;)

Je note en passant que grep -m 1 n'est pas standard (c'est une extension GNU, également disponible sur MacOS X). Et, en effet, l'option -n de echo est également non standard; vous feriez mieux de supprimer simplement les deux points de fin ajoutés en vertu de la conversion de la nouvelle ligne de l'écho en deux points. Puisque path-element-by-pattern est utilisé une seule fois et a des effets secondaires indésirables (il bloque toute variable exportée préexistante appelée $ removestr ), il peut être remplacé de manière judicieuse par son corps. Ceci, associé à une utilisation plus libérale des guillemets pour éviter les problèmes d'espaces ou d'expansion indésirable des noms de fichiers, conduit à:

.
/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

J'ai un script Perl appelé echopath que je trouve utile lors du débogage de problèmes avec des variables de type PATH:

replace_path PATH /usr/bin /work/bin

Lorsque j'exécute la solution modifiée sur le code de test ci-dessous:

list=$(eval echo '

Le résultat est:

# 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 '

Cela me semble correct, du moins pour ma définition du problème.

Je remarque que echopath LD_LIBRARY_PATH évalue $ LD_LIBRARY_PATH . Ce serait bien si vos fonctions pouvaient faire cela, ainsi l'utilisateur pourrait taper:

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

Cela peut être fait en utilisant:

<*>

Ceci conduit à cette révision du code:

<*>

Le test révisé suivant fonctionne désormais également:

<*>

Il produit le même résultat qu'auparavant.

$path)

Le résultat est:

<*>

Cela me semble correct, du moins pour ma définition du problème.

Je remarque que echopath LD_LIBRARY_PATH évalue $ LD_LIBRARY_PATH . Ce serait bien si vos fonctions pouvaient faire cela, ainsi l'utilisateur pourrait taper:

<*>

Cela peut être fait en utilisant:

<*>

Ceci conduit à cette révision du code:

<*>

Le test révisé suivant fonctionne désormais également:

<*>

Il produit le même résultat qu'auparavant.

$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 '

Cela me semble correct, du moins pour ma définition du problème.

Je remarque que echopath LD_LIBRARY_PATH évalue $ LD_LIBRARY_PATH . Ce serait bien si vos fonctions pouvaient faire cela, ainsi l'utilisateur pourrait taper:

<*>

Cela peut être fait en utilisant:

<*>

Ceci conduit à cette révision du code:

<*>

Le test révisé suivant fonctionne désormais également:

<*>

Il produit le même résultat qu'auparavant.

$path)

Le résultat est:

<*>

Cela me semble correct, du moins pour ma définition du problème.

Je remarque que echopath LD_LIBRARY_PATH évalue $ LD_LIBRARY_PATH . Ce serait bien si vos fonctions pouvaient faire cela, ainsi l'utilisateur pourrait taper:

<*>

Cela peut être fait en utilisant:

<*>

Ceci conduit à cette révision du code:

<*>

Le test révisé suivant fonctionne désormais également:

<*>

Il produit le même résultat qu'auparavant.

$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" }

Cela me semble correct, du moins pour ma définition du problème.

Je remarque que echopath LD_LIBRARY_PATH évalue $ LD_LIBRARY_PATH . Ce serait bien si vos fonctions pouvaient faire cela, ainsi l'utilisateur pourrait taper:

<*>

Cela peut être fait en utilisant:

<*>

Ceci conduit à cette révision du code:

<*>

Le test révisé suivant fonctionne désormais également:

<*>

Il produit le même résultat qu'auparavant.

$path)

Le résultat est:

<*>

Cela me semble correct, du moins pour ma définition du problème.

Je remarque que echopath LD_LIBRARY_PATH évalue $ LD_LIBRARY_PATH . Ce serait bien si vos fonctions pouvaient faire cela, ainsi l'utilisateur pourrait taper:

<*>

Cela peut être fait en utilisant:

<*>

Ceci conduit à cette révision du code:

<*>

Le test révisé suivant fonctionne désormais également:

<*>

Il produit le même résultat qu'auparavant.

Autres conseils

Republier ma réponse dans Quel est le moyen le plus élégant de supprimer un chemin de la variable $ PATH dans 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[*]}"

ou le one-liner:

PATH=$(IFS=':';t=($PATH);unset IFS;t=(${t[@]%%*usr*});IFS=':';echo "${t[*]}");

Pour supprimer un élément, vous pouvez utiliser sed:

#!/bin/bash
NEW_PATH=$(echo -n $PATH | tr ":" "\n" | sed "/foo/d" | tr "\n" ":")
export PATH=$NEW_PATH

supprimera les chemins contenant "foo". depuis le chemin.

Vous pouvez également utiliser sed pour insérer une nouvelle ligne avant ou après une ligne donnée.

Modifier: vous pouvez supprimer les doublons en passant par tri et uniq:

echo -n $PATH | tr ":" "\n" | sort | uniq -c | sed -n "/ 1 / s/.*1 \(.*\)/\1/p" | sed "/foo/d" | tr "\n" ":"

Il existe plusieurs programmes pertinents dans les réponses à " Comment éviter de dupliquer la variable de chemin dans csh " ;. Ils se concentrent davantage sur la nécessité d'éviter les éléments répétés, mais le script que je fournis peut être utilisé comme suit:

export PATH=$(clnpath $head_dirs:$PATH:$tail_dirs $remove_dirs)

En supposant que vous ayez un ou plusieurs répertoires dans $ head_dirs et un ou plusieurs répertoires dans $ tail_dirs et un ou plusieurs répertoires dans $ remove_dirs, il utilise ensuite le shell pour concaténer les parties head, current et tail dans une valeur énorme, et supprime ensuite chacun des répertoires répertoriés dans $ remove_dirs du résultat (pas une erreur s'ils n'existent pas), ainsi que l'élimination des occurrences secondes et ultérieures de tout répertoire dans le chemin.

Cela ne concerne pas le placement des composants de chemin d'accès dans une position spécifique (autre qu'au début ou à la fin, et ceux indirectement). Notamment, spécifier où vous voulez ajouter le nouvel élément ou quel élément vous souhaitez remplacer est compliqué.

Juste une note que bash elle-même peut rechercher et remplacer. Il peut effectuer toutes les opérations normales "une fois ou tous", dans les options sensibles que vous attendez.

À partir de la page de manuel:

$ {paramètre / modèle / chaîne}

Le motif est développé pour produire un motif exactement comme dans l’extension de nom de chemin. Le paramètre est développé et la correspondance la plus longue du motif avec sa valeur est remplacée par une chaîne. Si Ipattern commence par /, toutes les correspondances de modèle sont remplacées par une chaîne. Normalement, seul le premier match est remplacé. Si motif commence par #, il doit correspondre au début de la valeur étendue du paramètre. Si motif commence par%, il doit correspondre à la fin de la valeur étendue du paramètre. Si la chaîne est null, les correspondances de modèle sont supprimées et le modèle / suivant peut être omis. Si le paramètre est @ ou *, l'opération de substitution est appliquée à chaque paramètre de position et l'extension est la liste résultante. Si paramètre est une variable de tableau indexée avec @ ou *, l'opération de substitution est appliquée à chaque membre du tableau à son tour, et l'extension est la liste résultante.

Vous pouvez également effectuer une division de champ en définissant $ IFS (séparateur de champ de saisie) sur le délimiteur souhaité.

OK, merci à tous les répondants. J'ai préparé une version encapsulée de la réponse de Florin. La première passe ressemble à ceci:

# 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;
}

Il faut encore que toutes les fonctions soient interceptées par des erreurs, et je devrais probablement m'en tenir à une solution de chemin répété tant que j'y serai.

Vous l'utilisez en faisant un . /include/path/path_tools.bash dans le script de travail et appel des fonctions replace-path * .

Je suis toujours ouvert aux nouvelles et / ou meilleures réponses.

C’est facile avec awk.

Remplacer

{
  for(i=1;i<=NF;i++) 
      if($i == REM) 
          if(REP)
              print REP; 
          else
              continue;
      else 
          print $i; 
}

Lancez-le avec

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

Ajouter

Insère à la position donnée. Par défaut, il est ajouté à la fin.

{ 
    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
}

Lancez-le avec

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

Supprimer les doublons

Celui-ci conserve les premières occurrences.

{ 
    for(i = 1; i <= NF; i++) {
        if(!used[$i]) {
            print $i
            used[$i] = 1
        }
    }
}

Commencez comme ça:

echo $PATH | awk -F: -f rem_dup.awk | paste -sd:

Validez si tous les éléments existent

Ce qui suit imprimera un message d'erreur pour toutes les entrées qui n'existent pas dans le système de fichiers et retournera une valeur différente de zéro.

echo -n $PATH | xargs -d: stat -c %n

Pour vérifier simplement si tous les éléments sont des chemins et obtenir un code retour, vous pouvez également utiliser test :

echo -n $PATH | xargs -d: -n1 test -d

supposons

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

Si vous souhaitez supprimer /lib/jvm/java-1.6.0/bin/ faites comme ci-dessous

export PATH=$(echo $PATH | sed  's/\/lib\/jvm\/java-1.6.0\/bin\/://g')

sed prendra l'entrée de echo $ PATH et remplacera /lib/jvm/java-1.6.0/bin/: avec empty

De cette façon, vous pouvez supprimer

  • L'ordre de PATH n'est pas distribué
  • Traite les cas d'angle tels que chemin vide ou espace dans le chemin avec élégance
  • La correspondance partielle de dir ne donne pas de faux positifs
  • Traite le chemin en tête et en queue de PATH de manière appropriée. Pas de : déchets et autres.

Dis que tu as     / foo: / some / path: / some / path / dir1: / some / path / dir2: / bar et vous voulez remplacer     / un / chemin Ensuite, il remplace correctement "/ some / path". mais laisse " / some / path / dir1 " ou "/ some / path / dir2", selon vos attentes.

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  
}  

Article lié Quel est le moyen le plus élégant de supprimer un chemin de la variable $ PATH dans Bash?

Je préfère utiliser le rubis aux goûts de awk / sed / foo ces jours-ci, alors voici mon approche pour traiter les dupes,

# add it to the path
PATH=~/bin/:$PATH:~/bin
export PATH=$(ruby -e 'puts ENV["PATH"].split(/:/).uniq.join(":")')

créer une fonction à réutiliser,

mungepath() {
   export PATH=$(ruby -e 'puts ENV["PATH"].split(/:/).uniq.join(":")')
}

Hash, tableaux et chaînes dans une doublure en rubis:)

La première chose qui m’arrive à l’esprit de changer une partie de la chaîne est une substitution sed.

exemple: si echo $ PATH = > "/ usr / pkg / bin: / usr / bin: / bin: / usr / pkg / games: / usr / pkg / X11R6 / bin" puis pour changer " / usr / bin " dans / usr / local / bin " pourrait être fait comme ceci:

## produit un fichier de sortie standard

## the " = " le caractère est utilisé à la place de la barre oblique ("/") car ce serait désordonné,  # le caractère de citation alternatif devrait être peu probable dans PATH

## le caractère séparateur de chemin """: " est à la fois enlevé et rajouté ici,  # peut vouloir un colon supplémentaire après le dernier chemin

echo $ PATH | sed '= / usr / bin: = / usr / local / bin: ='

Cette solution remplace un élément de chemin entier. Elle peut donc être redondante si new-element est similaire.

Si les nouveaux PATH'-s ne sont pas dynamiques mais toujours dans des ensembles constants, vous pouvez enregistrer ceux-ci dans une variable et les affecter au besoin:

CHEMIN = $ TEMP_PATH_1;  # commandes ...; \ n PATH = $ TEMP_PATH_2;  # commandes etc ...;

Pourrait ne pas être ce que vous pensiez. certaines des commandes pertinentes sur bash / unix seraient:

pushd popd CD ls # peut-être l -1A pour une colonne unique; trouver grep # qui pourrait confirmer que ce fichier est d’où il vient; env tapez

.. et tout cela et plus encore quelques portant sur PATH ou les répertoires en général. La partie qui modifie le texte pourrait se faire de plusieurs façons!

Quelle que soit la solution choisie, elle comporterait 4 parties:

1) chercher le chemin tel quel 2) décoder le chemin pour trouver la partie nécessitant des modifications 3) déterminer quels changements sont nécessaires / intégrer ces changements 4) validation / intégration finale / définition de la variable

Conformément à la réponse de dj_segfault , je le fais dans des scripts qui ajoutent / préfixent des variables d'environnement pouvant être exécutées plusieurs fois. :

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}}

L'utilisation de cette même technique pour supprimer, remplacer ou manipuler des entrées dans PATH est simple compte tenu de la correspondance de modèle semblable à une extension de nom de fichier et de la prise en charge de la liste des modèles pour l'expansion des paramètres du shell.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top