¿Cómo añadir correctamente una ruta al PATH?

Me pregunto dónde hay que añadir una nueva ruta a la variable de entorno PATH. Sé que esto se puede lograr mediante la edición de .bashrc (por ejemplo), pero no está claro cómo hacerlo.

De esta manera:

lenguaje: bash -->

export PATH=~/opt/bin:$PATH

o esto?

export PATH=$PATH:~/opt/bin
Solución

The simple stuff

PATH=$PATH:~/opt/bin

o

PATH=~/opt/bin:$PATH

dependiendo de si quiere añadir ~/opt/bin al final (para que se busque después de todos los demás directorios, en caso de que haya un programa con el mismo nombre en varios directorios) o al principio (para que se busque antes de todos los demás directorios).

Puede añadir varias entradas al mismo tiempo. PATH=$PATH:~/opt/bin:~/opt/node/bin o variaciones en el ordenamiento funcionan bien. No pongas export al principio de la línea ya que tiene complicaciones adicionales (ver más abajo en "Notas sobre shells diferentes a bash").

Si su PATH es construido por muchos componentes diferentes, podría terminar con entradas duplicadas. Consulta https://unix.stackexchange.com/questions/25605/how-to-add-home-directory-path-to-be-discovered-by-unix-which-command y https://unix.stackexchange.com/questions/40749/remove-duplicate-path-entries-with-awk-command para evitar añadir duplicados o eliminarlos.

Algunas distribuciones ponen automáticamente ~/bin en su PATH si existe, por cierto.

Dónde ponerlo

Ponga la línea para modificar PATH en ~/.profile, o en ~/.bash_profile si eso es lo que tiene.

Tenga en cuenta que ~/.bash_rc no es leído por ningún programa, y que ~/.bashrc es el archivo de configuración de las instancias interactivas de bash. No debe definir variables de entorno en ~/.bashrc. El lugar correcto para definir variables de entorno como PATH es ~/.profile (o ~/.bash_profile si no le interesan otros shells que no sean bash). Ver ¿Cuál es la diferencia entre ellos y cuál debo usar?

No lo ponga en /etc/environment o ~/.pam_environment: estos no son archivos de shell, no puede usar sustituciones como $PATH en ellos. En estos archivos, sólo puede anular una variable, no añadirla.

Complicaciones potenciales en algunos scripts del sistema

No necesitas exportar si la variable ya está en el entorno: cualquier cambio del valor de la variable se refleja en el entorno.¹ PATH está casi siempre en el entorno; todos los sistemas unix lo establecen muy pronto (normalmente en el primer proceso, de hecho).

En el momento de iniciar la sesión, puede confiar en que PATH ya está en el entorno, y ya contiene algunos directorios del sistema. Si estás escribiendo un script que puede ser ejecutado antes mientras se configura algún tipo de entorno virtual, puedes necesitar asegurarte de que PATH no esté vacío y sea exportado: si PATH aún no está configurado, entonces algo como PATH=$PATH:/alguna/directorio establecería PATH a :/alguna/directorio, y el componente vacío al principio significa el directorio actual (como .:/alguna/directorio).

if [ -z "${PATH-}" ]; then export PATH=/usr/local/bin:/usr/bin:/bin; fi

Notas sobre shells diferentes a bash

En bash, ksh y zsh, exportar es una sintaxis especial, y tanto PATH=~/opt/bin:$PATH como exportar PATH=~/opt/bin:$PATH hacen lo correcto incluso. En otros shells estilo Bourne/POSIX como dash (que es /bin/sh en muchos sistemas), export se analiza como un comando ordinario, lo que implica dos diferencias:

Así, en shells como dash, exportar PATH=~/opt/bin:$PATH establece PATH a la cadena literal ~/opt/bin/: seguida del valor de PATH hasta el primer espacio. PATH=~/opt/bin:$PATH (una asignación desnuda) no requiere comillas y hace lo correcto. Si quiere usar exportar en un script portable, necesita escribir exportar PATH="$HOME/opt/bin:$PATH", o PATH=~/opt/bin:$PATH; exportar PATH (o PATH=$HOME/opt/bin:$PATH; exportar PATH para la portabilidad incluso al shell Bourne que no aceptaba exportar var=value y no hacía expansión de tilde).

Esto no era cierto en los shells Bourne (como en el verdadero shell Bourne, no en los shells modernos estilo POSIX), pero es muy poco probable que te encuentres con shells tan antiguos hoy en día;

Comentarios (3)

Cualquiera de las dos formas funciona, pero no hacen lo mismo: los elementos de PATH se comprueban de izquierda a derecha. En tu primer ejemplo, los ejecutables en ~/opt/bin tendrán prioridad sobre los instalados, por ejemplo, en /usr/bin, lo que puede ser o no lo que quieres.

En particular, desde el punto de vista de la seguridad, es peligroso añadir rutas al frente, porque si alguien puede obtener acceso de escritura a tu ~/opt/bin, puede poner, por ejemplo, un ls diferente allí, que entonces probablemente usarías en lugar de /bin/ls sin darte cuenta. Ahora imagina lo mismo para ssh o tu navegador o tu elección... (Lo mismo ocurre con la colocación de . en su ruta).

Comentarios (2)

Me confunde la pregunta 2 (ya eliminada de la pregunta por tratarse de un tema no relacionado):

¿Qué's una forma viable de añadir más rutas en diferentes líneas? Inicialmente pensé que esto podría hacer el truco:

export PATH=$PATH:~/opt/bin export PATH=$PATH:~/opt/node/bin

pero no lo hace'porque la segunda asignación no' sólo anexa ~/opt/node/bin, sino también todo el PATH previamente asignado.

Esta es una posible solución:

export PATH=$PATH:~/opt/bin:~/opt/node/bin

pero para la legibilidad yo' preferiría tener una asignación para una ruta.

Si dices

PATH=~/opt/bin

eso'es todo lo que estará en su PATH. PATH es sólo una variable de entorno, y si quieres añadir algo al PATH, tienes que reconstruir la variable con exactamente el contenido que quieres. Es decir, lo que das como ejemplo a la pregunta 2 es exactamente lo que quieres hacer, a no ser que me esté perdiendo totalmente el sentido de la pregunta.

Yo uso ambas formas en mi código. Tengo un perfil genérico que instalo en todas las máquinas en las que trabajo y que tiene este aspecto, para dar cabida a los directorios que puedan faltar:

export PATH=/opt/bin:/usr/local/bin:/usr/contrib/bin:/bin:/usr/bin:/usr/sbin:/usr/bin/X11
# add optional items to the path
for bindir in $HOME/local/bin $HOME/bin; do
    if [ -d $bindir ]; then
        PATH=$PATH:${bindir}
    fi
done
Comentarios (1)