Supprimer les chemins redondants de la variable $ PATH

125

J'ai défini le même chemin dans la variable $ PATH 6 fois.

Je ne me déconnectais pas pour vérifier si cela fonctionnait.

Comment puis-je supprimer les doublons?

La variable $ PATH ressemble à ceci:

echo $PATH

/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/home/flacs/Programmes/USFOS/bin:/home/flacs/Programmes/USFOS/bin:/home/flacs/Programmes/USFOS/bin:/home/flacs/Programmes/USFOS/bin:/home/flacs/Programmes/USFOS/bin:/home/flacs/Programmes/USFOS/bin

Comment pourrais-je le réinitialiser à juste

/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games
charles hendry
la source
où l'avez-vous défini 6 fois? dans quels fichiers?
hovanessyan
3
duplication possible de Quelle est la manière la plus élégante de supprimer un chemin de la variable $ PATH dans Bash?
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

Réponses:

122

Vous exécutez simplement:

export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games

ce serait pour la session en cours, si vous voulez changer de façon permanente, ajoutez-le à n'importe quel .bashrc, bash.bashrc, / etc / profile - tout ce qui convient à votre système et aux besoins de l'utilisateur.

Remarque: ceci est pour Linux. Nous allons clarifier cela pour les nouveaux codeurs. (`, ') N'essayez pas de SET = ces.

hovanessyan
la source
oui, je les ai mis en permanence dans bash.bashrc. Alors la commande devrait-elle être quelque chose comme ça? echo 'export PATH=$PATH:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games' >> ~/.bashrc
charles hendry
le fait est qu'en fonction de votre système d'exploitation, une chaîne de configurations est exécutée. Vous devez vous assurer que la variable PATH n'est pas écrasée ultérieurement. Le moyen le plus simple de le faire (pour un utilisateur) est de l'écraser dans le fichier .bashrc personnel de l'utilisateur, qui se trouve généralement dans son répertoire personnel.
hovanessyan
1
votre commande définit le PATH sur - $ PATH (la valeur actuelle de PATH) + la chaîne / usr / local / sbin: / usr / local / bin: / usr / sbin: / usr / bin: / sbin: / bin: / usr / gam‌ es. Si vous voulez avoir uniquement la chaîne, supprimez $ PATH + le point-virgule (:) de votre commande. Peu importe si vous utilisez echo ou modifiez le fichier ~ / .bashrc à la main.
hovanessyan
le fichier bash.bashrc se trouve dans le dossier / etc. Cependant, il n'affiche pas la variable $ PATH, donc je ne sais pas où le modifier
charles hendry
dans votre premier commentaire, vous faites écho à ~ / .bashrc (citant: >> ~ / .bashrc), pas à /etc/bash.bashrc. Si vous souhaitez modifier le PATH pour un utilisateur spécifique, modifiez-le dans le fichier / home / <le nom de l'utilisateur> /. Bashrc. le /etc/bash.bashrc s'applique à tous les utilisateurs.
hovanessyan
70

Si vous utilisez Bash, vous pouvez également effectuer les opérations suivantes si, disons, vous souhaitez supprimer le répertoire /home/wrong/dir/de votre PATHvariable:

PATH=`echo $PATH | sed -e 's/:\/home\/wrong\/dir\/$//'`
sufinawaz
la source
1
Cela m'a été utile, car un répertoire a été ajouté dans / etc / profile que je souhaitais exclure, mais je n'ai pas d'accès en écriture à / etc. Merci :)
Samizdis
13
Protip: vous pouvez utiliser différents déliminateurs dans l'expression sed pour éviter l'échappement \ /:PATH=$(echo $PATH | sed -e 's|:/home/wrong/dir|$||')
iNecas
4
Cette astuce est utile lorsque je veux avoir un nouveau PATH tout de suite et que je ne veux pas me déconnecter du terminal actuel. Cependant, pour éviter de gâcher, il faut expérimenter la commande de génération PATH (c'est-à-dire echo $PATH | sed -e 's/:\/home\/wrong\/dir\/$//') avant de l'assigner à PATH.
biocyberman
2
Cela ne fonctionnera pas lorsque le chemin à supprimer est le premier chemin d'accès $PATH. Utilisez celui-ci:PATH=$(echo :$PATH: | sed -e 's,:/home/wrong/dir:,:,g' -e 's/^://' -e 's/:$//')
Robin Hsu
n'a pas fonctionné $ PATH=echo $ PATH | sed -e 's /: \ / scratch \ / sjn \ / anaconda \ / bin \ / python \ / $ //' `` pour supprimer / scratch / sjn / anaconda / bin / python
Mona Jalal
13

Linux: supprimer les chemins redondants de la variable $ PATH

Linux From Scratch a cette fonction dans / etc / profile

# Functions to help us manage paths.  Second argument is the name of the
# path variable to be modified (default: PATH)
pathremove () {
        local IFS=':'
        local NEWPATH
        local DIR
        local PATHVARIABLE=${2:-PATH}
        for DIR in ${!PATHVARIABLE} ; do
                if [ "$DIR" != "$1" ] ; then
                  NEWPATH=${NEWPATH:+$NEWPATH:}$DIR
                fi
        done
        export $PATHVARIABLE="$NEWPATH"
}

Ceci est destiné à être utilisé avec ces fonctions pour ajouter au chemin, afin de ne pas le faire de manière redondante:

pathprepend () {
        pathremove $1 $2
        local PATHVARIABLE=${2:-PATH}
        export $PATHVARIABLE="$1${!PATHVARIABLE:+:${!PATHVARIABLE}}"
}

pathappend () {
        pathremove $1 $2
        local PATHVARIABLE=${2:-PATH}
        export $PATHVARIABLE="${!PATHVARIABLE:+${!PATHVARIABLE}:}$1"
}

L'utilisation simple consiste simplement à donner pathremovele chemin du répertoire à supprimer - mais gardez à l'esprit qu'il doit correspondre exactement:

$ pathremove /home/username/anaconda3/bin

Cela supprimera chaque instance de ce répertoire de votre chemin.

Si vous voulez le répertoire dans votre chemin, mais sans les redondances, vous pouvez simplement utiliser l'une des autres fonctions, par exemple - pour votre cas spécifique:

$ pathprepend /usr/local/sbin
$ pathappend /usr/local/bin
$ pathappend /usr/sbin
$ pathappend /usr/bin
$ pathappend /sbin
$ pathappend /bin
$ pathappend /usr/games

Mais, à moins que la lisibilité ne soit le problème, à ce stade, vous feriez mieux de simplement faire:

$ export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games

Est-ce que ce qui précède fonctionnerait dans toutes les coquilles connues de l'homme?

Je présume ci - dessus au travail sh, dashet bashau moins. Je serais surpris d'apprendre que cela ne fonctionne pas dans csh, fish', orksh`. Je doute que cela fonctionne dans le shell de commande Windows ou Powershell.

Si vous avez Python, le type de commande suivant devrait faire ce qui est directement demandé (c'est-à-dire supprimer les chemins redondants):

$ PATH=$( python -c "
import os
path = os.environ['PATH'].split(':')
print(':'.join(sorted(set(path), key=path.index)))
" )

Une ligne unique (pour éviter les problèmes multilignes):

$ PATH=$( python -c "import os; path = os.environ['PATH'].split(':'); print(':'.join(sorted(set(path), key=path.index)))" )

Ce qui précède supprime les chemins redondants ultérieurs. Pour supprimer les chemins redondants antérieurs, utilisez l'index d'une liste inversée et inversez-le à nouveau:

$ PATH=$( python -c "
import os
path = os.environ['PATH'].split(':')[::-1]
print(':'.join(sorted(set(path), key=path.index, reverse=True)))
" )
Salle Aaron
la source
+1. pathremove () fonctionne-t-il dans toutes les saveurs de shell, comme, csh, ksh, bash etc? btw, mon / etc / profile sur RHEL n'a pas partremove (), mais seulement pathmunge ().
Tagar
1
@Tagar Je ne donne aucune garantie sur la compatibilité avec tous les autres shells. Je suggère de le tester sur le shell que vous utilisez, et si cela ne fonctionne pas pour votre shell, vous pouvez utiliser Python si vous l'avez installé - j'ai ajouté du Python à la réponse pour décrire comment.
Aaron Hall
Si je lis correctement "3.5.3 Expansion des paramètres du shell", ${!PATHVARIABLE}c'est une sorte d'indirection variable, mais je ne sais pas comment cela fonctionne ici. Pourriez-vous l'expliquer s'il vous plaît?
loxaxs
@loxaxs C'est une variable locale dans ces fonctions bash, déclarée avec le localbuiltin (qui ne peut être utilisé qu'à l'intérieur d'une fonction.) Si vous avez d'autres questions, vous devriez probablement poser une nouvelle question sur le site (après l'avoir recherchée d'abord pour vous assurer vous ne créez pas un duplicata exact ...).
Aaron Hall
C'est une réponse vraiment intéressante, merci pour la rédaction! Cependant, la question originale de nettoyer une variable PATH foirée ne semble pas être résolue avec élégance (bien que, je l'admets, alors en utilisant ces fonctions, on ne se retrouverait pas avec un PATH foiré pour commencer).
Christian Herenz
9

Voici un code d'une ligne qui nettoie le CHEMIN

  • Cela ne perturbe pas l'ordre du PATH, supprime simplement les doublons
  • Traite: et empth PATH gracieusement
  • Aucun caractère spécial utilisé, donc ne nécessite pas d'échappement
  • Utilise /bin/awkpour que cela fonctionne même lorsque PATH est cassé

    export PATH="$(echo "$PATH" |/bin/awk 'BEGIN{RS=":";}
    {sub(sprintf("%c$",10),"");if(A[$0]){}else{A[$0]=1;
    printf(((NR==1)?"":":")$0)}}')";
GreenFox
la source
1
quelqu'un l'a testé? est sécurisé?
Joe RR
2
si vous n'avez pas installé awk, il nettoie votre chemin, je vous conseille de copier votre chemin dans un fichier txt avant avec echo $ PATH
Jose Pita
Cela ne fonctionne pas pour moi ... J'ai installé awk, mais certains doublons ne sont pas supprimés.
Christian Herenz
3
  1. Juste echo $PATH
  2. copier les détails dans un éditeur de texte
  3. supprimer les entrées indésirables
  4. PATH= # pass new list of entries
Mrwagaba
la source
2

Si vous souhaitez simplement supprimer les chemins en double, j'utilise ce script que j'ai écrit il y a quelque temps car j'avais des problèmes avec plusieurs chemins perl5 / bin:

#!/bin/bash
#
# path-cleanup
#
# This must be run as "source path-cleanup" or ". path-cleanup"
# so the current shell gets the changes.

pathlist=`echo $PATH | sed 's/:/\n/g' | uniq`

# echo "Starting PATH: $PATH"
# echo "pathlist: $pathlist"
unset PATH
# echo "After unset, PATH: $PATH"
for dir in $pathlist
do
    if test -d $dir ; then
        if test -z $PATH; then
            PATH=$dir
        else
            PATH=$PATH:$dir
        fi
    fi
done
export PATH
# echo "After loop, PATH: $PATH"

Et je l'ai mis dans mon ~ / .profile à la fin. Depuis que j'utilise BASH presque exclusivement, je ne l'ai pas essayé dans d'autres shells.

Kevin Nathan
la source
1
+1 pour la solution. Btw, cela ne supprimera les chemins de duplication que s'ils vont dans la liste les uns après les autres. Vous pouvez changer |uniqpour |sort|uniqrésoudre ce problème, mais cela changera l'ordre de tous les répertoires dans le chemin, ce que je ne pense pas être un effet secondaire souhaitable.
Tagar
1

En supposant que votre shell est Bash, vous pouvez définir le chemin avec

export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games

mais comme Levon l'a dit dans une autre réponse, dès que vous terminerez le shell, les changements disparaîtront. Vous souhaitez probablement configurer votre PATHin ~/.bash_profileou ~/.bashrc.

Leo
la source
1

Dans bash, vous pouvez simplement $ {var / find / replace}

PATH=${PATH/%:\/home\/wrong\/dir\//}

Ou dans ce cas (car le bit de remplacement est vide) simplement:

PATH=${PATH%:\/home\/wrong\/dir\/}

Je suis venu ici en premier, mais je suis allé ailleurs car je pensais qu'il y aurait une expansion des paramètres pour le faire. Plus facile que sed !.

Comment remplacer un caractère ou un mot d'espace réservé dans une variable par la valeur d'une autre variable dans Bash?

sabgenton
la source
%signifie match si à la fin de la chaîne, #c'est pour le début.
sabgenton
0

Il n’existe pas d’outils standard pour «modifier» la valeur de $PATH (c'est-à-dire "ajouter un dossier uniquement quand il n'existe pas déjà" ou "supprimer ce dossier").

Pour vérifier quel serait le chemin lors de votre prochaine connexion, utilisez telnet localhost(outelnet 127.0.0.1 ). Il vous demandera ensuite votre nom d'utilisateur et votre mot de passe.

Cela vous donne un nouveau shell de connexion (c'est-à-dire un tout nouveau qui n'hérite de rien de l'environnement actuel).

Vous pouvez vérifier la valeur de $PATHlà et modifier vos fichiers rc jusqu'à ce qu'il soit correct. Ceci est également utile pour voir si vous pouvez vous reconnecter après avoir modifié un fichier important.

Aaron Digulla
la source
Au lieu d'avoir à taper le nom d'utilisateur / mot de passe, tapez simplement /bin/bash -i. Beaucoup moins de tracas.
Ed Heal
0

Comment avez-vous ajouté ces chemins en double à votre variable PATH? Vous devez avoir édité l'un de vos .fichiers. ( .tcshrcou.bashrc , etc. en fonction de votre système / shell particulier). La façon de résoudre ce problème est de modifier à nouveau le fichier et de supprimer les chemins en double.

Si vous n'avez modifié aucun fichier et que vous devez avoir modifié le PATH de manière interactive. Dans ce cas, les modifications ne "colleront" pas, c'est-à-dire que si vous ouvrez un autre shell, ou si vous vous déconnectez et vous reconnectez, les modifications disparaîtront automatiquement.

Notez qu'il existe également des fichiers de configuration à l'échelle du système, mais il est peu probable que vous les ayez modifiés, il est donc fort probable que vous changiez des fichiers dans votre répertoire personnel (si vous souhaitez rendre ces modifications permanentes une fois que vous vous êtes installé sur un ensemble de chemins)

Levon
la source
0

Pour un modèle de copier-coller facile, j'utilise cet extrait de code Perl:

PATH=`echo $PATH | perl -pe s:/path/to/be/excluded::`

De cette façon, vous n'avez pas besoin d'échapper aux barres obliques pour l'opérateur de substitution.

Alexander Shcheblikin
la source