Me gustaría una manera de agregar cosas a $ PATH, en todo el sistema o para un usuario individual, sin potencialmente agregar la misma ruta varias veces.
Una razón para querer hacer esto es para que se puedan hacer adiciones .bashrc
, lo que no requiere un inicio de sesión, y también es más útil en sistemas que usan (por ejemplo) lightdm
, que nunca llama .profile
.
Soy consciente de las preguntas que tratan sobre cómo limpiar duplicados de $ PATH, pero no quiero eliminar duplicados . Me gustaría una forma de agregar rutas solo si aún no están presentes.
Respuestas:
Supongamos que la nueva ruta que queremos agregar es:
Luego, usando cualquier shell POSIX, podemos probar para ver si
new
ya está en la ruta y agregarlo si no lo está:Tenga en cuenta el uso de dos puntos. Sin los dos puntos, podríamos pensar que, por ejemplo,
new=/bin
ya estaba en el camino porque el patrón coincidía/usr/bin
. Mientras que las RUTA normalmente tienen muchos elementos, también se manejan los casos especiales de cero y un elemento en la RUTA. El caso de la PATH inicialmente no tener elementos (siendo vacío) es manejado por el uso de${PATH:=$new}
que asignaPATH
a$new
si está vacío. Establecer valores predeterminados para los parámetros de esta manera es una característica de todos los shells POSIX: consulte la sección 2.6.2 de los documentos POSIX ).Una función invocable
Por conveniencia, el código anterior se puede poner en una función. Esta función se puede definir en la línea de comando o, para tenerla disponible permanentemente, ponerla en el script de inicialización de su shell (para usuarios bash, eso sería
~/.bashrc
):Para usar esta función de actualización de ruta para agregar un directorio a la RUTA actual:
fuente
PATH
está vacío, esto agregará una entrada vacía (es decir, el directorio actual) alPATH
. Creo que necesitas otro caso.case
. Solo hazlocase "${PATH:=$new}"
. Vea mi propia respuesta para fallos similares.Cree un archivo
/etc/profile.d
llamado, por ejemplo,mypath.sh
(o lo que quiera). Si está utilizando lightdm, asegúrese de que sea viable o de lo contrario utilice/etc/bashrc
o un archivo procedente de la misma. Agregue a eso las siguientes funciones:Las cosas al comienzo de (antes) $ PATH tienen prioridad sobre lo que sigue, y por el contrario, las cosas al final (agregadas) serán reemplazadas por lo que viene antes. Esto significa que si su $ PATH es
/usr/local/bin:/usr/bin
y hay un ejecutablegotcha
en ambos directorios, el de adentro/usr/local/bin
se usará por defecto.Ahora puede, en este mismo archivo, en otro archivo de configuración de shell o desde la línea de comandos, usar:
Si esto está en a
.bashrc
, evitará que el valor aparezca más de una vez cuando inicie un nuevo shell. Hay una limitación en que si desea agregar algo que se antepuso (es decir, mover una ruta dentro de $ PATH) o viceversa, tendrá que hacerlo usted mismo.fuente
$PATH
conIFS=:
finalmente es más flexible quecase
.case
, IMO. Me imagino que tambiénawk
podría usarse aquí.gawk
podría asignar directamente$PATH
.Puedes hacerlo de esta manera:
Nota: si crea RUTA a partir de otras variables, verifique que no estén vacías, ya que muchos shells interpretan "" me gusta "". .
fuente
-q
POSIX requiere grep, pero no sé si eso significa que todavía hay algunos greps (no POSIX) que no lo tienen./my/bin
La parte importante del código es verificar si
PATH
contiene una ruta específica:Es decir, asegúrese de que cada ruta en
PATH
esté delimitada en ambos lados por elPATH
separador (:
), luego verifique (-q
) si la cadena literal (-F
) que consiste en unPATH
separador, su ruta y otroPATH
separador existe allí. Si no es así, puede agregar la ruta de forma segura:Esto debería ser compatible con POSIX y debería funcionar con cualquier ruta que no contenga un carácter de nueva línea. Es más complejo si desea que funcione con rutas que contengan nueva línea mientras sea compatible con POSIX, pero si tiene un
grep
soporte-z
que pueda usar, puede usarlo.fuente
He estado llevando esta pequeña función conmigo en varios
~/.profile
archivos durante años. Yo creo que fue escrito por el administrador de sistemas en un laboratorio que solía trabajar en, pero no estoy seguro. De todos modos, es similar al enfoque de Goldilock pero ligeramente diferente:Entonces, para agregar un nuevo directorio al comienzo de
PATH
:y hasta el final:
fuente
/bin/grep
->grep
ACTUALIZAR:
Me di cuenta de que su propia respuesta tenía una función separada cada una para agregar o anteponer al
$PATH
. Me gustó la idea. Así que agregué un pequeño manejo de argumentos. También lo_
separé correctamente :SALIDA:
De forma predeterminada,
-A
dependerá de$PATH
, pero puede modificar este comportamiento para que se-P
agregue agregando un-P
lugar en su lista de argumentos. Puede volver a-A
ponerlo en espera entregándolo-A
nuevamente.EVALO SEGURO
En la mayoría de los casos, recomiendo que las personas eviten el uso de
eval
. Pero esto, creo, se destaca como un ejemplo de su uso para bien. En este caso, la única declaración queeval
puede ver esP=
oA=
. Los valores de sus argumentos se prueban estrictamente antes de que se llame. Esto es para lo queeval
sirve.Esto aceptará tantos argumentos como le des y agregará cada uno
$PATH
solo una vez y solo si aún no está en$PATH
. Solo utiliza el script de shell POSIX totalmente portátil, se basa solo en los shell incorporados y es muy rápido.fuente
_
viene la idea de que las funciones de prefijo de shell las hacen "espaciadas correctamente"? En otros idiomas, generalmente indicaría una función global interna (es decir, una que debe ser global, pero no está destinada a ser utilizada externamente como parte de una API). Mis nombres ciertamente no son buenas opciones, pero me parece que el solo uso_
no resuelve los problemas de colisión en absoluto; sería mejor agregar un espacio de nombres real, por ejemplo.mikeserv_path_assign()
._
entonces necesita cambiar los administradores de paquetes. En cualquier caso, esto, esencialmente, es solo una "función global, interna" : es global para cada shell invocado desde el shell en el que se declara, y es solo un poco de script de lenguaje interpretado que cuelga en la memoria del intérprete . unix.stackexchange.com/questions/120528/…unset a
(o equivalente) al final del perfil?¡Mirad! La función de 12 líneas de fuerza industrial ... técnicamente bash y zsh-portable que adora tu script de inicio
~/.bashrc
o~/.zshrc
de elección:Prepárate para la gloria instantánea. Entonces, en lugar de hacer esto y deseando lo mejor:
Haga esto en su lugar y tenga la garantía de obtener lo mejor, ya sea que realmente quiera eso o no:
Muy bien, defina "Mejor".
Anexar y anteponer con seguridad a la corriente
${PATH}
no es el asunto trivial que comúnmente se supone que es. Si bien son convenientes y aparentemente razonables, las frases ingeniosas del formularioexport PATH=$PATH:~/opt/bin
invitan a complicaciones diabólicas con:Nombres de directorio relativos accidentalmente (por ejemplo,
export PATH=$PATH:opt/bin
). Si bienbash
y enzsh
silencio aceptan e ignoran en su mayoría los nombres de directorios relativos en la mayoría de los casos, los nombres de directorios relativos con el prefijo unoh
ot
(y posiblemente otros caracteres nefastos) hacen que ambos se mutilen vergonzosamente por Harakiri, la obra maestra seminal de 1962 de Masaki Kobayashi :Accidentalmente nombres de directorio duplicados. Si bien los
${PATH}
nombres de directorio duplicados son en gran medida inocuos, también son indeseados, engorrosos, ligeramente ineficientes, impiden la depuración y promueven el desgaste de la unidad, como esta respuesta. Mientras que los SSD de estilo NAND son ( por supuesto ) inmunes al desgaste de lectura, los HDD no lo son. El acceso innecesario al sistema de archivos en cada intento de comando implica un desgaste innecesario del cabezal de lectura al mismo tempo. Los duplicados son particularmente untuosos cuando se invocan proyectiles anidados en subprocesos anidados, momento en el cual las frases ingenuas aparentemente inocuasexport PATH=$PATH:~/wat
explotan rápidamente en el Séptimo Círculo del${PATH}
InfiernoPATH=/usr/local/bin:/usr/bin:/bin:/home/leycec/wat:/home/leycec/wat:/home/leycec/wat:/home/leycec/wat
. Solo Beelzebubba puede ayudarlo si luego agrega nombres de directorio adicionales. (No dejes que esto le pase a tus preciosos hijos. )${PATH}
nombres de directorio faltantes son en gran medida inocuos, también suelen ser no deseados, engorrosos, ligeramente ineficientes, impiden la depuración y promueven el desgaste de la unidad.Ergo, automatización amigable como la función de shell definida anteriormente. Debemos salvarnos de nosotros mismos.
Pero ... ¿Por qué "+ path.append ()"? ¿Por qué no simplemente append_path ()?
Para de desambiguación (por ejemplo, con comandos externos en las actuales
${PATH}
funciones de shell o del sistema definida en otra parte), funciones de shell definidos por el usuario son idealmente el prefijo o sufijo única subseries soportados porbash
yzsh
pero prohibidos de otro modo para nombres base comando estándar - como, por ejemplo,+
.Oye. Funciona. No me juzgues
Pero ... ¿Por qué "+ path.append ()"? ¿Por qué no "+ path.prepend ()"?
Debido a que agregar a la corriente
${PATH}
es más seguro que anteponer a la corriente${PATH}
, todas las cosas son iguales, lo que nunca son. Anular comandos de todo el sistema con comandos específicos del usuario puede ser insalubre en el mejor de los casos y loco en el peor En Linux, por ejemplo, las aplicaciones posteriores comúnmente esperan las variantes de comandos GNU coreutils en lugar de las derivadas o alternativas no estándar personalizadas.Dicho esto, absolutamente hay casos de uso válidos para hacerlo. Definir la
+path.prepend()
función equivalente es trivial. Sans prolix nebulosity, por su cordura compartida:Pero ... ¿por qué no Gilles?
La respuesta aceptada de Gilles en otra parte es impresionantemente óptima en el caso general como un "agregado idempotente agnóstico de caparazón" . En el caso común de
bash
yzsh
con no hay enlaces simbólicos indeseables, sin embargo, la penalización de rendimiento requerido para ello entristece la arrocera de Gentoo en mí. Incluso en presencia de enlaces simbólicos indeseables, es discutible si la bifurcación de un subshell poradd_to_PATH()
argumento vale la inserción potencial de duplicados de enlaces simbólicos.Para casos de uso estrictos que exigen que se eliminen incluso los duplicados de enlaces simbólicos, esta
zsh
variante específica lo hace a través de builtins eficientes en lugar de tenedores ineficientes:Tenga en cuenta el
*":${dirname:A}:"*
más que*":${dirname}:"*
el original.:A
es unzsh
ismos maravilloso tristemente ausente debajo de la mayoría de los otros caparazones, incluidobash
. Para citarman zshexpn
:No más preguntas.
De nada. Disfruta del bombardeo seguro. Ahora te lo mereces.
fuente
Aquí está mi versión de estilo de programación funcional.
*PATH
variable delimitada por dos puntos , no soloPATH
.También digno de mención:
export
ing; eso le queda a la persona que llama (ver ejemplos)bash
; sin bifurcaciónfuente
Este script le permite agregar al final de
$PATH
:O agregue al comienzo de
$PATH
:fuente