Me pregunto dónde se debe agregar una nueva ruta a la variable de entorno PATH
. Sé que esto se puede lograr editando .bashrc
(por ejemplo), pero no está claro cómo hacerlo.
De esta manera:
export PATH=~/opt/bin:$PATH
¿o esto?
export PATH=$PATH:~/opt/bin
PATH=$PATH:~/opt/bin
o
PATH=~/opt/bin:$PATH
dependiendo de si desea agregar ~/opt/bin
al final (para buscar todos los demás directorios, en caso de que haya un programa con el mismo nombre en varios directorios) o al principio (para buscar antes de todos los demás directorios).
Puede agregar varias entradas al mismo tiempo. PATH=$PATH:~/opt/bin:~/opt/node/bin
o variaciones en el orden funcionan bien. No coloque export
al comienzo de la línea, ya que tiene complicaciones adicionales (ver más abajo en "Notas sobre los depósitos que no sean bash").
Si su PATH
es construido por muchos componentes diferentes, puede terminar con entradas duplicadas. Consulte ¿Cómo agregar la ruta del directorio personal para que Unix descubra qué comando? y Eliminar entradas duplicadas de $ PATH con el comando awk para evitar agregar duplicados o eliminarlos.
Algunas distribuciones ponen automáticamente ~/bin
en su RUTA si existe, por cierto.
Ponga la línea para modificar PATH
en ~/.profile
, o en ~/.bash_profile
si eso es lo que tienes.
Tenga en cuenta que ~/.bash_rc
no es leído por ningún programa, y ~/.bashrc
es el archivo de configuración de 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 te importan las conchas que no sean bash). Ver ¿Cuál es la diferencia entre ellos y cuál debo usar?
No lo pongas en /etc/environment
o ~/.pam_environment
: estos no son archivos Shell, no puedes usar sustituciones como $PATH
ahí. En estos archivos, solo puede anular una variable, no agregarla.
No necesita export
si la variable ya está en el entorno: cualquier cambio en el valor de la variable se refleja en el entorno.¹ PATH
está casi siempre en el entorno; todos los sistemas unix lo configuraron desde el principio (de hecho, generalmente en el primer proceso).
En el momento de iniciar sesión, puede confiar en que PATH
ya está en el entorno y contiene algunos directorios del sistema. Si está escribiendo una secuencia de comandos que puede ejecutarse antes mientras configura algún tipo de entorno virtual, es posible que deba asegurarse de que PATH
no esté vacío y se exporte: si PATH
aún no está configurado , entonces algo como PATH=$PATH:/some/directory
establecería PATH
en :/some/directory
, y el componente vacío al principio significa el directorio actual (como .:/some/directory
).
if [ -z "${PATH-}" ]; then export PATH=/usr/local/bin:/usr/bin:/bin; fi
En bash, ksh y zsh, export
es una sintaxis especial, y ambas PATH=~/opt/bin:$PATH
y export PATH=~/opt/bin:$PATH
hacer lo correcto incluso. En otros shells de estilo Bourne/POSIX como el guión (que es /bin/sh
en muchos sistemas), export
se analiza como un comando ordinario, lo que implica dos diferencias:
~
solo se analiza al comienzo de una palabra, excepto en las asignaciones (consulte ¿Cómo agregar la ruta del directorio personal que Unix descubrirá qué comando? para más detalles);$PATH
fuera de las comillas dobles se rompe si PATH
contiene espacios en blanco o \[*?
.Entonces en conchas como guiones, establece export PATH=~/opt/bin:$PATH
PATH
en la cadena literal ~/opt/bin/:
seguido del valor de PATH
hasta el primer espacio. PATH=~/opt/bin:$PATH
(una tarea básica) no requiere comillas y hace lo correcto. Si desea utilizar export
en un script portátil, debe escribir export PATH="$HOME/opt/bin:$PATH"
o PATH=~/opt/bin:$PATH; export PATH
(o PATH=$HOME/opt/bin:$PATH; export PATH
para portabilidad incluso para el Bourne Shell que no aceptó export var=value
y no hice tilde expansión).
¹ Esto no era cierto en los shells Bourne (como en el Bourne Shell real, no en los shells modernos de estilo POSIX), pero es muy poco probable que encuentre estos shells viejos en estos días.
De cualquier manera funciona, pero no hacen lo mismo: los elementos de PATH
se verifican de izquierda a derecha. En su primer ejemplo, ejecutables en ~/opt/bin
tendrá prioridad sobre los instalados, por ejemplo, en /usr/bin
, que puede o no ser lo que quieres.
En particular, desde un punto de vista de seguridad, es peligroso agregar rutas al frente, porque si alguien puede obtener acceso de escritura a su ~/opt/bin
, pueden poner, por ejemplo, un ls
diferente allí, que probablemente usarías en lugar de /bin/ls
sin darse cuenta. Ahora imagine lo mismo para ssh
o para su navegador o elección ... (Lo mismo se triplica para ponerlo en su camino).
Estoy confundido con la pregunta 2 (ya que se eliminó de la pregunta porque se debió a un problema no relacionado):
¿Cuál es una forma viable de agregar 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 solo agrega
~/opt/node/bin
, pero también todo elPATH
asignado previamente.Esta es una posible solución alternativa:
export PATH=$PATH:~/opt/bin:~/opt/node/bin
pero para facilitar la lectura, preferiría tener una asignación para una ruta.
Si usted dice
PATH=~/opt/bin
eso es todos que estará en su RUTA. RUTA es solo una variable de entorno, y si desea agregar a la RUTA, debe reconstruir la variable con exactamente el contenido que desea. Es decir, lo que da como ejemplo a la pregunta 2 es exactamente lo que quiere hacer, a menos que me esté perdiendo totalmente el punto de la pregunta.
Yo uso ambos formularios en mi código. Tengo un perfil genérico que instalo en cada máquina en la que trabajo que se ve así, para acomodar directorios que pueden 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
Linux determina la ruta de búsqueda ejecutable con $PATH
Variable ambiental. Para agregar directorio/datos/myscripts al comienzo de $PATH
variable de entorno, use lo siguiente:
PATH=/data/myscripts:$PATH
Para agregar ese directorio al final de la ruta, use el siguiente comando:
PATH=$PATH:/data/myscripts
Pero lo anterior no es suficiente porque cuando establece una variable de entorno dentro de un script, ese cambio es efectivo solo dentro del script. Solo hay dos formas de evitar esta limitación:
Ejemplos:
$HOME/myscript.sh
source $HOME/myscript.sh
La inclusión básicamente incorpora el guión "llamado" en el guión "llamado". Es como un #include en C. Por lo tanto, es efectivo dentro del script o programa "llamado". Pero, por supuesto, no es efectivo en ningún programa o script llamado por el programa de llamada. Para que sea efectivo en toda la cadena de llamadas, debe seguir la configuración de la variable de entorno con un comando de exportación.
Como ejemplo, el programa bash Shell incorpora los contenidos del archivo .bash_profile por inclusión. Coloque las siguientes 2 líneas en .bash_profile:
PATH=$PATH:/data/myscripts
export PATH
efectivamente coloca esas 2 líneas de código en el programa bash. Entonces, dentro de bash, la variable $ PATH incluye $HOME/myscript.sh
, y debido a la declaración de exportación, cualquier programa llamado por bash tiene la alteración $PATH
variable. Y debido a que cualquier programa que ejecute desde un indicador de bash se llama mediante bash, la nueva ruta está en vigor para todo lo que ejecute desde el indicador de bash.
La conclusión es que para agregar un nuevo directorio a la ruta, debe agregar o anteponer el directorio a la variable de entorno $ PATH dentro de un script incluido en el Shell, y debe exportar el $PATH
Variable ambiental.
Más información aquí
Desde hace algún tiempo he guardado conmigo dos funciones pathadd
y pathrm
que ayudan a agregar elementos a la ruta sin la necesidad de preocuparse por las duplicaciones.
pathadd
toma un argumento de ruta única y un argumento opcional after
que, si se proporciona, se agregará al PATH
de lo contrario lo antepone.
En casi todas las situaciones, si está agregando a la ruta, es probable que desee anular cualquier cosa que ya esté en la ruta, por lo que opto por anteponer por defecto.
pathadd() {
newelement=${1%/}
if [ -d "$1" ] && ! echo $PATH | grep -E -q "(^|:)$newelement($|:)" ; then
if [ "$2" = "after" ] ; then
PATH="$PATH:$newelement"
else
PATH="$newelement:$PATH"
fi
fi
}
pathrm() {
PATH="$(echo $PATH | sed -e "s;\(^\|:\)${1%/}\(:\|\$\);\1\2;g" -e 's;^:\|:$;;g' -e 's;::;:;g')"
}
Ponga esto en cualquier script que desee alterar el entorno PATH y ahora puede hacerlo.
pathadd "/foo/bar"
pathadd "/baz/bat" after
export PATH
Le garantizamos que no agregará a la ruta si ya está allí. Si ahora quieres asegurarte /baz/bat
está al comienzo.
pathrm "/baz/bat"
pathadd "/baz/bat"
export PATH
Ahora cualquier camino se puede mover al frente si ya está en el camino sin duplicarlo.
No puedo hablar por otras distribuciones, pero Ubuntu tiene un archivo,/etc/environment, que es la ruta de búsqueda predeterminada para todos los usuarios. Como mi computadora solo la uso yo, pongo los directorios que quiero en mi camino allí, a menos que sea una adición temporal que coloque en un script.
Hay algunas situaciones en las que se usa PATH=/a/b:$PATH
podría considerarse la forma "incorrecta" de agregar una ruta a PATH
:
PATH
en la misma forma.PATH
en una forma diferente (es decir, un alias debido al uso de enlaces simbólicos o ..
).PATH
cuando se pretende anular otras entradas en PATH
.Esta función (solo Bash) hace lo "correcto" en las situaciones anteriores (con una excepción, ver más abajo), devuelve códigos de error e imprime mensajes de Niza para humanos. Los códigos y mensajes de error se pueden deshabilitar cuando no se desean.
prepath() {
local usage="\
Usage: prepath [-f] [-n] [-q] DIR
-f Force dir to front of path even if already in path
-n Nonexistent dirs do not return error status
-q Quiet mode"
local tofront=false errcode=1 qecho=echo
while true; do case "$1" in
-f) tofront=true; shift;;
-n) errcode=0; shift;;
-q) qecho=':'; shift;;
*) break;;
esac; done
# Bad params always produce message and error code
[[ -z $1 ]] && { echo 1>&2 "$usage"; return 1; }
[[ -d $1 ]] || { $qecho 1>&2 "$1 is not a directory."; return $errcode; }
dir="$(command cd "$1"; pwd -P)"
if [[ :$PATH: =~ :$dir: ]]; then
$tofront || { $qecho 1>&2 "$dir already in path."; return 0; }
PATH="${PATH#$dir:}" # remove if at start
PATH="${PATH%:$dir}" # remove if at end
PATH="${PATH//:$dir:/:}" # remove if in middle
fi
PATH="$dir:$PATH"
}
La excepción es que esta función no canoniza las rutas agregadas a PATH
por otros medios, por lo que si un alias no canónico para una ruta está en PATH
, esto agregará un duplicado. Intentar canonizar rutas que ya están en PATH
es una propuesta incierta ya que una ruta relativa tiene un significado obvio cuando se pasa a prepath
pero cuando ya está en la ruta no sabes cuál era el directorio de trabajo actual cuando fue agregado.
Para agregar una nueva ruta a la variable de entorno PATH
:
export PATH=$PATH:/new-path/
Para que este cambio se aplique a cada Shell que abra, agréguelo al archivo que el Shell fuente cuando se invoca. En diferentes shells esto puede ser:
p.ej.
# export PATH=$PATH:/root/learning/bin/
# source ~/.bashrc
# echo $PATH
Puede ver la ruta proporcionada en la salida anterior.
Para mí (en Mac OS X 10.9.5), agregar el nombre de la ruta (por ejemplo, /mypathname
) al archivo /etc/paths
funcionó muy bien.
Antes de editar, echo $PATH
devoluciones:
/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin
Después de editar /etc/paths
y reiniciando el Shell, la variable $ PATH se agrega con /pathname
. En efecto, echo $PATH
devoluciones:
/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/mypathname
Lo que pasó es que /mypathname
se ha agregado al $PATH
variable.
Aquí está mi solución:
PATH=$(echo -n $PATH | awk -v RS=: -v ORS=: '!x[$0]++' | sed "s/\(.*\).\{1\}/\1/")
Un buen y sencillo revestimiento que no deja un rastro :