Eliminar rutas redundantes de la variable $ PATH

125

He definido la misma ruta en la variable $ PATH 6 veces.

No estaba cerrando sesión para comprobar si funcionaba.

¿Cómo puedo eliminar los duplicados?

La variable $ PATH se ve así:

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

¿Cómo lo restablecería a solo

/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games
Charles Hendry
fuente
¿Dónde lo has definido 6 veces? en que archivos?
hovanessyan
3
posible duplicado de ¿Cuál es la forma más elegante de eliminar una ruta de la variable $ PATH en Bash?
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

Respuestas:

122

Simplemente ejecutas:

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

eso sería para la sesión actual, si desea cambiar permanentemente, agréguelo a cualquier .bashrc, bash.bashrc, / etc / profile, lo que se ajuste a las necesidades de su sistema y usuario.

Nota: Esto es para Linux. Dejaremos esto claro para los nuevos codificadores. (`, ') No intente SET = estos.

hovanessyan
fuente
sí, los configuré permanentemente en bash.bashrc. Entonces, ¿el comando debería ser algo como esto? echo 'export PATH=$PATH:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games' >> ~/.bashrc
charles hendry
La cuestión es que, dependiendo de su sistema operativo, se ejecuta una cadena de configuraciones. Debe asegurarse de que la variable PATH no se sobrescriba más tarde. La forma más fácil de hacerlo (para un usuario) es sobrescribirlo en el archivo .bashrc personal del usuario, que comúnmente se encuentra en su directorio de inicio.
hovanessyan
1
su comando establece PATH en - $ PATH (el valor actual de PATH) + la cadena / usr / local / sbin: / usr / local / bin: / usr / sbin: / usr / bin: / sbin: / bin: / usr / gam‌es. Si desea tener solo la cadena, elimine $ PATH + el punto y coma (:) de su comando. No importa si usa echo o edita el archivo ~ / .bashrc a mano.
hovanessyan
el archivo bash.bashrc se encuentra en la carpeta / etc. No muestra la variable $ PATH sin embargo, así que no estoy seguro de dónde editarlo
Charles Hendry
en su primer comentario se hace eco a ~ / .bashrc (citando: >> ~ / .bashrc), no a /etc/bash.bashrc. Si desea cambiar la RUTA de un usuario específico, edítela en el archivo / home / <nombre del usuario> /. Bashrc. /etc/bash.bashrc se aplica a todos los usuarios.
hovanessyan
70

Si está utilizando Bash, también puede hacer lo siguiente si, digamos, desea eliminar el directorio /home/wrong/dir/de su PATHvariable:

PATH=`echo $PATH | sed -e 's/:\/home\/wrong\/dir\/$//'`
sufinawaz
fuente
1
Esto fue útil para mí, ya que se agregó un directorio en / etc / profile que deseaba excluir, pero no tengo acceso de escritura a / etc. Gracias :)
Samizdis
13
Protip: puede usar un deliminador diferente en la expresión sed para evitar el \ / escape:PATH=$(echo $PATH | sed -e 's|:/home/wrong/dir|$||')
iNecas
44
Este truco ayuda cuando quiero tener una nueva RUTA de inmediato y no quiero cerrar sesión en el terminal actual. Sin embargo, para evitar errores, uno debe experimentar con el comando generador de RUTA (es decir echo $PATH | sed -e 's/:\/home\/wrong\/dir\/$//') antes de asignarlo a RUTA.
biocyberman
2
Esto no funcionará cuando la ruta que se va a eliminar sea la primera ruta $PATH. Utilice este:PATH=$(echo :$PATH: | sed -e 's,:/home/wrong/dir:,:,g' -e 's/^://' -e 's/:$//')
Robin Hsu
no funcionó $ PATH=echo $ PATH | sed -e 's /: \ / scratch \ / sjn \ / anaconda \ / bin \ / python \ / $ //' '`para eliminar / scratch / sjn / anaconda / bin / python
Mona Jalal
13

Linux: eliminar rutas redundantes de la variable $ PATH

Linux From Scratch tiene esta función en / 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"
}

Está destinado a ser utilizado con estas funciones para agregar a la ruta, para que no lo haga de forma redundante:

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

El uso simple es simplemente dar pathremovela ruta del directorio para eliminar, pero tenga en cuenta que tiene que coincidir exactamente:

$ pathremove /home/username/anaconda3/bin

Esto eliminará cada instancia de ese directorio de su ruta.

Si desea el directorio en su ruta, pero sin las redundancias, puede usar una de las otras funciones, por ejemplo, para su caso específico:

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

Pero, a menos que la legibilidad sea la preocupación, en este punto es mejor que solo haga lo siguiente:

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

¿Funcionaría lo anterior en todos los depósitos conocidos por el hombre?

Yo presumiría lo anterior para el trabajo en sh, dashy bashpor lo menos. Me sorprendería aprender que no funciona en csh, fish', orksh`. Dudo que funcione en el shell de comandos de Windows o Powershell.

Si tiene Python, el siguiente tipo de comando debe hacer lo que se le pide directamente (es decir, eliminar rutas redundantes):

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

Una línea (para evitar problemas multilínea):

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

Lo anterior elimina las rutas redundantes posteriores. Para eliminar rutas redundantes anteriores, use el índice de una lista inversa y vuelva a invertirlo:

$ PATH=$( python -c "
import os
path = os.environ['PATH'].split(':')[::-1]
print(':'.join(sorted(set(path), key=path.index, reverse=True)))
" )
Aaron Hall
fuente
+1. ¿pathremove () funciona en todos los sabores de shell, como csh, ksh, bash, etc.? Por cierto, mi / etc / profile en RHEL no tiene partremove (), pero solo tiene pathmunge ().
Tagar
1
@Tagar No garantizo la compatibilidad con todos los demás shells. Sugiero probarlo en cualquier shell que esté usando, y si no funciona para su shell, puede usar Python si lo tiene instalado. Agregué un poco de Python a la respuesta para describir cómo.
Aaron Hall
Si leo "3.5.3 Expansión de parámetros de shell" correctamente, ${!PATHVARIABLE}es una especie de indirección variable, pero no estoy seguro de cómo funciona aquí. ¿Podría explicarlo por favor?
loxaxs
@loxaxs Esa es una variable local en esas funciones bash, declarada con el localincorporado (que solo se puede usar dentro de una función). Si tiene más preguntas, probablemente debería hacer una nueva pregunta en el sitio (después de buscarla primero para asegurarse no estás creando un duplicado exacto ...).
Aaron Hall
Esta es una respuesta realmente interesante, ¡gracias por el informe! Sin embargo, la cuestión original de limpiar una variable PATH desordenada parece no resolverse con elegancia (aunque, lo admito, entonces, al usar estas funciones, uno no terminaría con un PATH desordenado para empezar).
Christian Herenz
9

Aquí hay un código de una línea que limpia la RUTA

  • No altera el orden de la RUTA, solo elimina duplicados
  • Trata: y empth RUTA con gracia
  • No se utilizan caracteres especiales, por lo que no requiere escape
  • Utiliza /bin/awkpara que funcione incluso cuando la RUTA está rota

    export PATH="$(echo "$PATH" |/bin/awk 'BEGIN{RS=":";}
    {sub(sprintf("%c$",10),"");if(A[$0]){}else{A[$0]=1;
    printf(((NR==1)?"":":")$0)}}')";
GreenFox
fuente
1
alguien lo probó? ¿es seguro?
Joe RR
2
si no tiene instalado awk, limpia su ruta, le aconsejo que copie su ruta a un archivo txt antes con echo $ PATH
Jose Pita
No funciona para mí ... tengo awk instalado, pero algunos duplicados no se eliminan.
Christian Herenz
3
  1. Sólo echo $PATH
  2. copiar detalles en un editor de texto
  3. eliminar entradas no deseadas
  4. PATH= # pass new list of entries
mrwagaba
fuente
2

Si solo desea eliminar cualquier ruta duplicada, utilizo este script que escribí hace un tiempo ya que tenía problemas con múltiples rutas 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"

Y lo puse en mi perfil ~ /. Al final. Como uso BASH casi exclusivamente, no lo he probado en otros shells.

Kevin Nathan
fuente
1
+1 para la solución. Por cierto, solo eliminará las rutas de duplicación si van en la lista una tras otra. Puede cambiar |uniqa |sort|uniqpara solucionar esto, pero esto cambiará el orden de todos los directorios en la ruta, lo que no creo que sea un efecto secundario deseable.
Tagar
1

Suponiendo que su shell es Bash, puede establecer el camino con

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

pero como dijo Levon en otra respuesta, tan pronto como termine el shell, los cambios se habrán ido. Es posible que desee configurar su PATHen ~/.bash_profileo ~/.bashrc.

León
fuente
1

En bash simplemente puedes $ {var / find / replace}

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

O en este caso (ya que el bit de reemplazo está vacío) simplemente:

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

Vine aquí primero, pero fui a lo demás porque pensé que habría una expansión de parámetros para hacer esto. Más fácil que sed!

¿Cómo reemplazar el carácter o la palabra del marcador de posición en la variable con el valor de otra variable en Bash?

sabgenton
fuente
%significa coincidencia si al final de la cadena, #es para el comienzo.
sabgenton
0

No existen herramientas estándar para "editar" el valor de $PATH(es decir, "agregar carpeta solo cuando aún no existe" o "eliminar esta carpeta").

Para verificar cuál sería la ruta la próxima vez que inicie sesión, use telnet localhost(o telnet 127.0.0.1). Luego le pedirá su nombre de usuario y contraseña.

Esto le proporciona un nuevo shell de inicio de sesión (es decir, uno completamente nuevo que no hereda nada del entorno actual).

Puede verificar el valor de $PATHallí y editar sus archivos rc hasta que sea correcto. Esto también es útil para ver si puede iniciar sesión nuevamente después de hacer un cambio en un archivo importante.

Aaron Digulla
fuente
En lugar de tener que escribir el nombre de usuario / contraseña, simplemente escriba /bin/bash -i. Mucho menos problemas.
Ed Heal
0

¿Cómo agregaste estas rutas duplicadas a tu variable PATH? Debes haber editado uno de tus .archivos. ( .tcshrc, o .bashrc, etc. dependiendo de su sistema / shell particular). La forma de solucionarlo es editar el archivo nuevamente y eliminar las rutas duplicadas.

Si no editó ningún archivo y debe haber modificado la RUTA de forma interactiva. En ese caso, los cambios no se "pegarán", es decir, si abre otro shell, o cierra sesión y vuelve a iniciar sesión, los cambios desaparecerán automáticamente.

Tenga en cuenta que también hay algunos archivos de configuración de todo el sistema, pero es poco probable que los haya modificado, por lo que lo más probable es que cambie los archivos en su directorio personal (si desea hacer esos cambios permanentes una vez que se establezca en un conjunto de rutas)

Levon
fuente
0

Para una plantilla fácil de copiar y pegar, uso este fragmento de Perl:

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

De esta manera, no necesita escapar de las barras para el operador sustituto.

Alexander Shcheblikin
fuente