Quelle est la façon la plus élégante de supprimer un chemin de la variable $PATH dans Bash?

ou plus généralement, Comment puis-je supprimer un élément d'une liste séparée par deux points dans une variable D'environnement Bash?

j'ai pensé que j'avais vu une façon simple de faire cela il y a des années, en utilisant les formes plus avancées de l'expansion variable de Bash, mais si c'est le cas, j'ai perdu la trace de celui-ci. Une recherche rapide de Google a produit étonnamment peu de résultats pertinents et aucun que je qualifierais de "simple" ou "élégant". Par exemple, deux méthodes utilisant sed et awk, respectivement:

PATH=$(echo $PATH | sed -e 's;:?/home/user/bin;;' -e 's;/home/user/bin:?;;')
PATH=!(awk -F: '{for(i=1;i<=NF;i++){if(!($i in a)){a[$i];printf s$i;s=":"}}}'<<<$PATH)

est - ce que rien de simple n'existe? Y a-t-il quelque chose d'analogue à une fonction split() dans Bash?

mise à jour:

Il semble que je doive m'excuser pour ma question intentionnellement vague; j'étais moins intéressé à résoudre un cas d'utilisation spécifique qu'à provoquer une bonne discussion. Heureusement, je l'ai eu!

il y a des techniques très intelligentes ici. En fin de compte, j'ai ajouté ce qui suit trois fonctions de ma boîte à outils. La magie se produit dans path_remove, qui est basé en grande partie sur L'utilisation Intelligente de Martin York de awk 'S RS variable.

path_append ()  { path_remove ; export PATH="$PATH:"; }
path_prepend () { path_remove ; export PATH=":$PATH"; }
path_remove ()  { export PATH=`echo -n $PATH | awk -v RS=: -v ORS=: '"151910920" != "''"' | sed 's/:$//'`; }

la seule vraie miette là-dedans est l'utilisation de sed pour enlever le colon traînant. Compte tenu de la simplicité du reste de la solution de Martin, cependant, je suis tout à fait prêt à vivre avec elle!


question connexe: comment manipuler les éléments $ PATH dans les scripts shell?

88
demandé sur Community 2008-12-16 02:19:14

30 réponses

Une minute avec awk:

# Strip all paths with SDE in them.
#
export PATH=`echo ${PATH} | awk -v RS=: -v ORS=: '/SDE/ {next} {print}'`

Edit: It réponse aux commentaires ci-dessous:

$ export a="/a/b/c/d/e:/a/b/c/d/g/k/i:/a/b/c/d/f:/a/b/c/g:/a/b/c/d/g/i"
$ echo ${a}
/a/b/c/d/e:/a/b/c/d/f:/a/b/c/g:/a/b/c/d/g/i

## Remove multiple (any directory with a: all of them)
$ echo ${a} | awk -v RS=: -v ORS=: '/a/ {next} {print}'
## Works fine all removed

## Remove multiple including last two: (any directory with g)
$ echo ${a} | awk -v RS=: -v ORS=: '/g/ {next} {print}'
/a/b/c/d/e:/a/b/c/d/f:
## Works fine: Again!

modifier en réponse à un problème de sécurité: (qui n'est pas pertinent à la question)

export PATH=$(echo ${PATH} | awk -v RS=: -v ORS=: '/SDE/ {next} {print}' | sed 's/:*$//')

cela supprime tous les colons traînants laissés en supprimant les dernières entrées, qui ajouteraient effectivement . à votre chemin.

37
répondu Martin York 2016-02-24 06:41:27

Mon sale hack:

echo ${PATH} > t1
vi t1
export PATH=$(cat t1)
47
répondu Martin York 2016-03-09 16:30:42

étant donné que le grand problème avec la substitution est la fin des cas, pourquoi ne pas faire en sorte que la fin des cas ne diffère pas des autres cas? Si le chemin avait déjà des colons au début et à la fin, nous pourrions simplement chercher notre chaîne désirée enveloppée de colons. Comme il est, nous pouvons facilement ajouter ces colons et les enlever après.

# PATH => /bin:/opt/a dir/bin:/sbin
WORK=:$PATH:
# WORK => :/bin:/opt/a dir/bin:/sbin:
REMOVE='/opt/a dir/bin'
WORK=${WORK/:$REMOVE:/:}
# WORK => :/bin:/sbin:
WORK=${WORK%:}
WORK=${WORK#:}
PATH=$WORK
# PATH => /bin:/sbin

Pur bash :).

35
répondu Andrew Aylett 2013-12-09 23:03:08

Voici la solution la plus simple que je puisse imaginer:

#!/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[*]}"

l'exemple ci-dessus supprimera tout élément dans $PATH qui contient"usr". Vous pouvez remplacer "*usr*" par "/home/user/bin" pour supprimer l'élément.

mise à jour par sschuberth

même si je pense que les espaces dans un $PATH sont une horrible idée, voici une solution que poignées:

PATH=$(IFS=':';t=($PATH);n=${#t[*]};a=();for ((i=0;i<n;i++)); do p="${t[i]%%*usr*}"; [ "${p}" ] && a[i]="${p}"; done;echo "${a[*]}");

ou

IFS=':'
t=($PATH)
n=${#t[*]}
a=()
for ((i=0;i<n;i++)); do
  p="${t[i]%%*usr*}"
  [ "${p}" ] && a[i]="${p}"
done
echo "${a[*]}"
23
répondu nicerobot 2017-05-23 12:18:20

voici un one-liner qui, malgré les réponses acceptées et les mieux notées , n'ajoute pas de caractères invisibles au chemin et peut faire face à des chemins qui contiennent des espaces:

export PATH=$(p=$(echo $PATH | tr ":" "\n" | grep -v "/cygwin/" | tr "\n" ":"); echo ${p%:})

personnellement, je trouve aussi cela facile à lire / comprendre, et cela implique seulement des commandes communes au lieu d'utiliser awk.

9
répondu sschuberth 2017-05-23 12:18:20
"151910920 de la fonction" __chemin_remove(){

local D=": $ {PATH}:";

[ "/:$1:/:}" != "$D"] & & PATH= " ${D/:$1:/:}";

PATH= " $ {PATH/#:/}";

export PATH= " ${PATH/%:/}";

}

L'a trouvé dans le mien .dossier bashrc. Quand vous jouez avec PATH, et qu'il se perd, awk/sed / grep devient indisponible :-)

6
répondu GreenFox 2012-08-13 00:28:39

la meilleure option pure bash que j'ai trouvé jusqu'à présent est la suivante:

function path_remove {
  PATH=${PATH/":"/} # delete any instances in the middle or at the end
  PATH=${PATH/":"/} # delete any instances at the beginning
}

ceci est basé sur la réponse pas tout à fait correcte à ajouter répertoire à $PATH si elle n'est pas déjà là plus sur Superuser.

6
répondu Mark Booth 2017-03-20 10:18:16

Voici une solution qui:

  • est un pur Bash,
  • n'invoque pas d'autres procédés (comme "sed" ou "awk"),
  • ne change pas IFS ,
  • n'est pas à la fourche d'un sous-shell,
  • poignées de chemins avec des espaces, et
  • supprime toutes les occurrences de l'argument dans PATH .

    removeFromPath() {
       local p d
       p="::"
       d=":$PATH:"
       d=${d//$p/:}
       d=${d/#:/}
       PATH=${d/%:/}
    }
6
répondu robinbb 2015-03-20 04:22:43

je viens d'utiliser les fonctions de la distribution bash, qui sont là apparemment depuis 1991. Ceux-ci sont toujours dans le paquet bash-docs sur Fedora, et étaient utilisés dans /etc/profile , mais pas plus...

$ rpm -ql bash-doc |grep pathfunc
/usr/share/doc/bash-4.2.20/examples/functions/pathfuncs
$ cat $(!!)
cat $(rpm -ql bash-doc |grep pathfunc)
#From: "Simon J. Gerraty" <sjg@zen.void.oz.au>
#Message-Id: <199510091130.VAA01188@zen.void.oz.au>
#Subject: Re: a shell idea?
#Date: Mon, 09 Oct 1995 21:30:20 +1000


# NAME:
#       add_path.sh - add dir to path
#
# DESCRIPTION:
#       These functions originated in /etc/profile and ksh.kshrc, but
#       are more useful in a separate file.
#
# SEE ALSO:
#       /etc/profile
#
# AUTHOR:
#       Simon J. Gerraty <sjg@zen.void.oz.au>

#       @(#)Copyright (c) 1991 Simon J. Gerraty
#
#       This file is provided in the hope that it will
#       be of use.  There is absolutely NO WARRANTY.
#       Permission to copy, redistribute or otherwise
#       use this file is hereby granted provided that
#       the above copyright notice and this notice are
#       left intact.

# is  missing from  (or PATH) ?
no_path() {
        eval "case :$${2-PATH}: in *::*) return 1;; *) return 0;; esac"
}
# if  exists and is not in path, append it
add_path () {
  [ -d ${1:-.} ] && no_path $* && eval ${2:-PATH}="$${2:-PATH}:"
}
# if  exists and is not in path, prepend it
pre_path () {
  [ -d ${1:-.} ] && no_path $* && eval ${2:-PATH}=":$${2:-PATH}"
}
# if  is in path, remove it
del_path () {
  no_path $* || eval ${2:-PATH}=`eval echo :'$'${2:-PATH}: |
    sed -e "s;::;:;g" -e "s;^:;;" -e "s;:$;;"`
}
5
répondu Mr. Wacky 2012-03-08 23:09:11

Eh bien, à bash, comme il soutient l'expression régulière, je ferais simplement:

PATH=${PATH/:\/home\/user\/bin/}
3
répondu mat 2008-12-15 23:23:54

j'ai écrit une réponse à ce ici (en utilisant awk aussi). Mais je ne suis pas certain de ce que vous recherchez? Il me semble au moins clair ce qu'il fait, au lieu d'essayer de rentrer dans une ligne. Pour une simple doublure, cependant, qui enlève seulement des trucs, je recommande

echo $PATH | tr ':' '\n' | awk '"151900920" != "/bin"' | paste -sd:

remplace

echo $PATH | tr ':' '\n' | 
    awk '"151910920" != "/bin"; "151910920" == "/bin" { print "/bar" }' | paste -sd:

ou (plus court mais moins lisible)

echo $PATH | tr ':' '\n' | awk '"151920920" == "/bin" { print "/bar"; next } 1' | paste -sd:

en tout cas, pour la même question, et un grand nombre de réponses utiles, voir ici .

3
répondu Johannes Schaub - litb 2017-05-23 12:34:37

Oui, mettre un côlon à la fin du chemin, par exemple, rend enlever un chemin un peu moins maladroit et sujet aux erreurs.

path_remove ()  { 
   declare i newPATH
   newPATH="${PATH}:"
   for ((i=1; i<=${#@}; i++ )); do
      #echo ${@:${i}:1}
      newPATH="${newPATH//${@:${i}:1}:/}" 
   done
   export PATH="${newPATH%:}" 
   return 0; 
} 

path_remove_all ()  {
   declare i newPATH
   shopt -s extglob
   newPATH="${PATH}:"
   for ((i=1; i<=${#@}; i++ )); do
      newPATH="${newPATH//+(${@:${i}:1})*([^:]):/}" 
      #newPATH="${newPATH//+(${@:${i}:1})*([^:])+(:)/}" 
   done
   shopt -u extglob 
   export PATH="${newPATH%:}" 
   return 0 
} 

path_remove /opt/local/bin /usr/local/bin

path_remove_all /opt/local /usr/local 
1
répondu cyrill 2010-01-21 19:58:30

si vous vous souciez de supprimer les doublons dans $PATH, la façon la plus élégante, IMHO, serait de ne pas les ajouter en premier lieu. En 1 ligne:

if ! $( echo "$PATH" | tr ":" "\n" | grep -qx "$folder" ) ; then PATH=$PATH:$folder ; fi

$dossier peut être remplacé par quelque chose, et peut contenir des espaces ("/home/user/mes documents")

1
répondu MestreLion 2011-02-19 05:11:25

la solution la plus élégante que j'ai trouvée à ce jour:

pathrm () {                                                                      
  local IFS=':'                                                                  
  local newpath                                                                  
  local dir                                                                      
  local pathvar=${2:-PATH}                                                       
  for dir in ${!pathvar} ; do                                                    
    if [ "$dir" != "" ] ; then                                                 
      newpath=${newpath:+$newpath:}$dir                                          
    fi                                                                           
  done                                                                           
  export $pathvar="$newpath"                                                        
}

pathprepend () {                                                                 
  pathrm                                                                     
  local pathvar=${2:-PATH}                                                       
  export $pathvar="${!pathvar:+:${!pathvar}}"                                  
}

pathappend () {                                                                    
  pathrm                                                                     
  local pathvar=${2:-PATH}                                                       
  export $pathvar="${!pathvar:+${!pathvar}:}"                                  
} 
1
répondu TriangleTodd 2012-04-07 05:29:34

la plupart des autres solutions proposées reposent uniquement sur l'appariement des chaînes et ne tiennent pas compte des segments de chemin contenant des noms spéciaux comme . , .. ou ~ . La fonction bash ci-dessous résout les chaînes de répertoires dans son argument et dans les segments de chemin pour trouver les correspondances de répertoires logiques aussi bien que les correspondances de chaînes.

rm_from_path() {
  pattern=""
  dir=''
  [ -d "${pattern}" ] && dir="$(cd ${pattern} && pwd)"  # resolve to absolute path

  new_path=''
  IFS0=${IFS}
  IFS=':'
  for segment in ${PATH}; do
    if [[ ${segment} == ${pattern} ]]; then             # string match
      continue
    elif [[ -n ${dir} && -d ${segment} ]]; then
      segment="$(cd ${segment} && pwd)"                 # resolve to absolute path
      if [[ ${segment} == ${dir} ]]; then               # logical directory match
        continue
      fi
    fi
    new_path="${new_path}${IFS}${segment}"
  done
  new_path="${new_path/#${IFS}/}"                       # remove leading colon, if any
  IFS=${IFS0}

  export PATH=${new_path}
}

Test:

$ mkdir -p ~/foo/bar/baz ~/foo/bar/bif ~/foo/boo/bang
$ PATH0=${PATH}
$ PATH=~/foo/bar/baz/.././../boo/././../bar:${PATH}  # add dir with special names
$ rm_from_path ~/foo/boo/../bar/.  # remove same dir with different special names
$ [ ${PATH} == ${PATH0} ] && echo 'PASS' || echo 'FAIL'
1
répondu jwfearn 2014-10-06 16:14:53

j'aime les trois fonctions présentées dans la mise à jour de @BenBlank à sa question originale. Pour les généraliser, j'utilise une forme à 2 arguments, qui me permet de définir le chemin ou toute autre variable d'environnement que je veux:

path_append ()  { path_remove  ; export ="${!1}:"; }
path_prepend () { path_remove  ; export =":${!1}"; }
path_remove ()  { export ="`echo -n ${!1} | awk -v RS=: -v ORS=: ' != "''"' | sed 's/:$//'`"; }

exemples d'utilisation:

path_prepend PATH /usr/local/bin
path_append PERL5LIB "$DEVELOPMENT_HOME/p5/src/perlmods"

notez que j'ai aussi ajouté quelques guillemets pour permettre le traitement correct des noms de chemins qui contiennent des espaces.

1
répondu Cary Millsap 2016-01-05 20:54:22

Quelle est la façon la plus élégante de supprimer un chemin de la variable $PATH dans Bash?

quoi de plus élégant qu'awk?

path_remove ()  { export PATH=`echo -n $PATH | awk -v RS=: -v ORS=: '"151900920" != "''"' | sed 's/:$//'`; 

Python! C'est une solution plus lisible et maintenable, et il est facile d'inspecter pour voir qu'il fait vraiment ce que vous voulez.

voulez-vous supprimer le premier élément de chemin?

PATH="$(echo "$PATH" | python -c "import sys; path = sys.stdin.read().split(':'); del path[0]; print(':'.join(path))")"

(au lieu de la tuyauterie de echo , os.getenv['PATH'] serait un peu plus courte, et fourni le même résultat que ci-dessus, mais je suis inquiet que Python pourrait faire quelque chose avec cette variable d'environnement, il est donc probablement préférable de la pipe directement à partir de l'environnement dont vous vous souciez.)

de même pour supprimer de la fin:

PATH="$(echo "$PATH" | python -c "import sys; path = sys.stdin.read().split(':'); del path[-1]; print(':'.join(path))")"

pour rendre ces fonctions shell réutilisables que vous pouvez, par exemple, coller dans votre .fichier bashrc:

strip_path_first () {
    PATH="$(echo "$PATH" | 
    python -c "import sys; path = sys.stdin.read().split(':'); del path[0]; print(':'.join(path))")"
}

strip_path_last () {
    PATH="$(echo "$PATH" | 
    python -c "import sys; path = sys.stdin.read().split(':'); del path[-1]; print(':'.join(path))")"
}
1
répondu Aaron Hall 2017-02-15 22:42:17

puisque cela tend à être assez problématique, car il N'y a pas de manière élégante, je recommande d'éviter le problème en réarrangeant la solution: construisez votre chemin vers le haut plutôt que de tenter de le démolir.

je pourrais être plus précis si je connaissais votre vrai contexte de problème. Dans l'intervalle, j'utiliserai une construction logicielle comme contexte.

un problème commun avec les constructions de logiciel est qu'il casse sur certaines machines, finalement en raison de la façon dont quelqu'un a configuré leur shell par défaut (chemin et autres variables d'environnement). La solution élégante est de rendre vos scripts de construction immunisés en spécifiant complètement l'environnement shell. Codez vos scripts de construction pour définir le chemin et d'autres variables d'environnement basées sur l'assemblage des pièces que vous contrôlez, telles que l'emplacement du compilateur, des bibliothèques, des outils, des composants, etc. Faites de chaque élément configurable quelque chose que vous pouvez individuellement définir, vérifier, puis utiliser de manière appropriée dans votre script.

par exemple, j'ai une construction Java basée sur Maven et ciblée sur le Web, dont j'ai hérité de mon nouvel employeur. Le script de construction est connu pour être fragile, et un autre nouvel employé et moi avons passé trois semaines (pas à temps plein, juste ici et là, mais encore de nombreuses heures) pour le faire fonctionner sur nos machines. Une étape essentielle était que j'ai pris le contrôle du chemin pour que je sache exactement quel Java, quel Maven, et quel WebLogic était invoqué. J'ai créé des variables d'environnement pour pointer chacun de ces outils, puis j'ai calculé le chemin basé sur ceux plus quelques autres. Des techniques similaires ont dompté les autres paramètres configurables, jusqu'à ce que nous ayons finalement créé une construction reproductible.

au fait, N'utilisez pas Maven, Java est correct, et n'achetez WebLogic que si vous avez absolument besoin de son clustering (mais sinon non, et surtout pas ses fonctionnalités propriétaires).

meilleurs voeux.

0
répondu Rob Williams 2008-12-16 00:21:26

comme avec @litb, j'ai répondu à la question " comment manipuler les éléments $PATH dans les scripts shell ", donc ma réponse principale est là.

la fonctionnalité" split "de bash et d'autres dérivés de la coque Bourne est parfaitement réalisée avec $IFS , le séparateur inter-champs. Par exemple, pour définir les arguments de position ( , , ...) aux éléments de PATH, utilisez:

set -- $(IFS=":"; echo "$PATH")

ça va marcher tant qu'il n'y a pas d'Espaces Dans $PATH. Le faire fonctionner pour des éléments de chemin contenant des espaces est un exercice non-trivial-laissé pour le lecteur intéressé. Il est probablement plus simple de le traiter en utilisant un langage de script tel que Perl.

j'ai aussi un script, clnpath , que j'utilise beaucoup pour définir mon chemin. Je l'ai documenté dans la réponse à " "Comment éviter de dupliquer la variable PATH dans csh ".

0
répondu Jonathan Leffler 2017-05-23 12:34:37

ce qui rend ce problème ennuyeux sont les cas de fencepost entre le premier et le dernier éléments. Le problème peut être résolu avec élégance en changeant de SI et en utilisant un tableau, mais je ne sais pas comment réintroduire le deux-points une fois que le chemin est converti en forme de tableau.

Voici une version légèrement moins élégante qui supprime un répertoire de $PATH en utilisant la manipulation de chaîne seulement. Je l'ai testé.

#!/bin/bash
#
#   remove_from_path dirname
#
#   removes  from user's $PATH

if [ $# -ne 1 ]; then
  echo "Usage: "151900920" pathname" 1>&2; exit 1;
fi

delendum=""
NEWPATH=
xxx="$IFS"
IFS=":"
for i in $PATH ; do
  IFS="$xxx"
  case "$i" in
    "$delendum") ;; # do nothing
    *) [ -z "$NEWPATH" ] && NEWPATH="$i" || NEWPATH="$NEWPATH:$i" ;;
  esac
done

PATH="$NEWPATH"
echo "$PATH"
0
répondu Norman Ramsey 2008-12-16 02:53:52

Voici une chemise Perl:

PATH=`perl -e '$a=shift;$_=$ENV{PATH};s#:$a(:)|^$a:|:$a$##;print' /home/usr/bin`

la variable $a obtient le chemin à supprimer. Les commandes s (substitute) et print fonctionnent implicitement sur la variable $_ .

0
répondu J. A. Faucett 2008-12-16 19:54:14

C'est bien. J'utilise celui-ci pour éviter d'ajouter des dupes en premier lieu.

#!/bin/bash
#
######################################################################################
#
# Allows a list of additions to PATH with no dupes
# 
# Patch code below into your $HOME/.bashrc file or where it
# will be seen at login.
#
# Can also be made executable and run as-is.
#
######################################################################################

# add2path=($HOME/bin .)                  ## uncomment space separated list 
if [ $add2path ]; then                    ## skip if list empty or commented out
for nodup in ${add2path[*]}
do
    case $PATH in                 ## case block thanks to MIKE511
    $nodup:* | *:$nodup:* | *:$nodup ) ;;    ## if found, do nothing
    *) PATH=$PATH:$nodup          ## else, add it to end of PATH or
    esac                          ## *) PATH=$nodup:$PATH   prepend to front
done
export PATH
fi
## debug add2path
echo
echo " PATH == $PATH"
echo
0
répondu ongoto 2010-01-13 09:28:52

avec globbing étendu permis il est possible de faire ce qui suit:

# delete all /opt/local paths in PATH
shopt -s extglob 
printf "%s\n" "${PATH}" | tr ':' '\n' | nl
printf "%s\n" "${PATH//+(\/opt\/local\/)+([^:])?(:)/}" | tr ':' '\n' | nl 

man bash | less -p extglob
0
répondu carlo 2010-01-20 18:28:13

Extended "globbing" one-liner (enfin, en quelque sorte):

path_remove ()  { shopt -s extglob; PATH="${PATH//+()+([^:])?(:)/}"; export PATH="${PATH%:}"; shopt -u extglob; return 0; } 

il ne semble pas nécessaire d'échapper à des coupures de 1$.

path_remove ()  { shopt -s extglob; declare escArg="${1//\//\/}"; PATH="${PATH//+(${escArg})+([^:])?(:)/}"; export PATH="${PATH%:}"; shopt -u extglob; return 0; } 
0
répondu carlo 2010-01-21 10:14:13

ajouter des colons au chemin nous pourrions aussi faire quelque chose comme:

path_remove ()  { 
   declare i newPATH
   # put a colon at the beginning & end AND double each colon in-between
   newPATH=":${PATH//:/::}:"   
   for ((i=1; i<=${#@}; i++)); do
       #echo ${@:${i}:1}
       newPATH="${newPATH//:${@:${i}:1}:/}"   # s/:\/fullpath://g
   done
   newPATH="${newPATH//::/:}"
   newPATH="${newPATH#:}"      # remove leading colon
   newPATH="${newPATH%:}"      # remove trailing colon
   unset PATH 
   PATH="${newPATH}" 
   export PATH
   return 0 
} 


path_remove_all ()  {
   declare i newPATH extglobVar
   extglobVar=0
   # enable extended globbing if necessary
   [[ ! $(shopt -q extglob) ]]  && { shopt -s extglob; extglobVar=1; }
   newPATH=":${PATH}:"
   for ((i=1; i<=${#@}; i++ )); do
      newPATH="${newPATH//:+(${@:${i}:1})*([^:])/}"     # s/:\/path[^:]*//g
   done
   newPATH="${newPATH#:}"      # remove leading colon
   newPATH="${newPATH%:}"      # remove trailing colon
   # disable extended globbing if it was enabled in this function
   [[ $extglobVar -eq 1 ]] && shopt -u extglob
   unset PATH 
   PATH="${newPATH}" 
   export PATH
   return 0 
} 

path_remove /opt/local/bin /usr/local/bin

path_remove_all /opt/local /usr/local 
0
répondu proxxy 2010-01-22 17:45:00

Dans path_remove_all (par proxxy):

-newPATH="${newPATH//:+(${@:${i}:1})*([^:])/}" 
+newPATH="${newPATH//:${@:${i}:1}*([^:])/}"        # s/:\/path[^:]*//g 
0
répondu marius 2010-01-22 18:34:52

bien que ce soit un fil très ancien, j'ai pensé que cette solution pourrait être d'intérêt:

PATH="/usr/lib/ccache:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games"
REMOVE="ccache" # whole or part of a path :)
export PATH=$(IFS=':';p=($PATH);unset IFS;p=(${p[@]%%$REMOVE});IFS=':';echo "${p[*]}";unset IFS)
echo $PATH # outputs /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games

trouvé sur ce post de blog . Je pense que je l'aime plus :)

0
répondu mjc 2011-06-22 21:18:07

j'ai adopté une approche légèrement différente de celle de la plupart des gens ici et je me suis concentré spécifiquement sur la manipulation de cordes, comme ceci:

path_remove () {
    if [[ ":$PATH:" == *"::"* ]]; then
        local dirs=":$PATH:"
        dirs=${dirs/::/:}
        export PATH="$(__path_clean $dirs)"
    fi
}
__path_clean () {
    local dirs=${1%?}
    echo ${dirs#?}
}

ce qui précède est un exemple simplifié des fonctions finales que j'utilise. J'ai aussi créé path_add_before et path_add_after vous permettant d'insérer un chemin avant/après un chemin spécifié déjà dans le chemin.

L'ensemble des fonctions sont disponibles en path_helpers.sh in my fichiers de configuration utilisateur . Ils supportent totalement la suppression/ajout/pré-ajout/insertion au début/milieu / fin de la chaîne de chemin.

0
répondu jimeh 2012-04-20 17:14:06

le": "est causé par le fait que vous définissez la fin de ligne, pas le séparateur. J'utilise des unités de ressources limitées et j'aime tout emballer dans un seul script, sans ces bizarreries:

path_remove () {
    PATH="$(echo -n $PATH | awk -v RS=: -v ORS= '"151900920" != "''"{print s _ "151900920";s=":"}')"
}
0
répondu Coroos 2014-05-16 19:36:52

c'est certes élégant, mais il utilise le sed externe. En outre, il supprime tous les chemins contenant la chaîne de recherche $1. Il ne laisse pas non plus de balancier : à la fin dans le cas où le chemin enlevé est le dernier sur le chemin.

PATH=`echo $PATH | sed 's/:[^:]*[^:]*//g'`

cette alternative laisse une finale pendante : cependant.

PATH=`echo $PATH | tr ":" "\n" | grep -v  | tr "\n" ":"`

Les solutions de rechange sans backticks sont:

PATH=$(echo $PATH | sed 's/:[^:]*[^:]*//g')

PATH=$(echo $PATH | tr ":" "\n" | grep -v  | tr "\n" ":")
0
répondu Eugene 2014-10-22 19:44:38