Me tomó casi 10 años de uso de Linux hacer esta pregunta. Todo fue prueba y error y navegación aleatoria por Internet a altas horas de la noche.
Pero la gente no debería necesitar 10 años para esto. Si recién comenzara con Linux, me gustaría saber: ¿ Cuándo usar un alias, cuándo escribir un script y cuándo escribir una función?
En lo que respecta a los alias, uso alias para operaciones muy simples que no toman argumentos.
alias houston='cd /home/username/.scripts/'
Eso parece obvio. Pero algunas personas hacen esto:
alias command="bash bashscriptname"
(y agregarlo al .bashrc
archivo)
¿Hay una buena razón para hacer eso? Estoy intentando mucho, pero realmente no puedo pensar en ninguna circunstancia en la que me gustaría hacer eso. Entonces, si hay un caso límite en el que eso marcaría la diferencia, responda a continuación.
Porque ahí es donde simplemente pondría algo en mi RUTA y chmod +x
eso, que es otra cosa que surgió después de años de prueba y error de Linux.
Lo que me lleva al siguiente tema. Por ejemplo, agregué una carpeta oculta ( .scripts/
) en el directorio de inicio a mi RUTA simplemente agregando una línea a mi .bashrc
( PATH=$PATH:/home/username/.scripts/
), por lo que todo lo ejecutable allí se autocompleta automáticamente.
Si lo necesitara.
Sin embargo, realmente no necesito eso, ¿verdad? Solo lo usaría para lenguajes que no son el shell, como Python.
Si es el shell, puedo escribir una función dentro del mismo .bashrc
:
funcname () {
somecommand -someARGS "$@"
}
Como dije, descubrí mucho de esto a través de prueba y error. Y realmente solo vi la belleza de las funciones cuando mi computadora murió y me vi obligado a usar las computadoras de las personas que me rodeaban cuando no las usaban.
En lugar de mover un directorio completo de scripts de computadora a computadora, terminé reemplazando el .bashrc de todos los demás por el mío, ya que nunca habían hecho una sola modificación.
¿Pero extrañé algo?
Entonces, ¿qué le diría a un usuario principiante de Linux sobre cuándo usar alias, cuándo escribir un script y cuándo escribir una función?
Si no es obvio, supongo que las personas que respondan esto harán uso de las tres opciones. Si solo usa alias, o solo usa scripts, o solo usa funciones, o si solo usa alias y scripts o alias y funciones o scripts y funciones, esta pregunta no está realmente dirigida a usted.
fuente
Respuestas:
Un alias no debería (en general) hacer más que cambiar las opciones predeterminadas de un comando. No es más que un simple reemplazo de texto en el nombre del comando. No puede hacer nada con argumentos, sino pasarlos al comando que realmente ejecuta. Entonces, si simplemente necesita agregar un argumento al frente de un solo comando, un alias funcionará. Ejemplos comunes son
Se debe usar una función cuando necesita hacer algo más complejo que un alias, pero eso no sería útil por sí solo. Por ejemplo, tome esta respuesta en una pregunta que hice sobre cómo cambiar
grep
el comportamiento predeterminado de acuerdo con si está en proceso:Es un ejemplo perfecto de una función porque es demasiado compleja para un alias (que requiere valores predeterminados diferentes según una condición), pero no es algo que necesitará en un script no interactivo.
Si obtiene demasiadas funciones o funciones demasiado grandes, colóquelas en archivos separados en un directorio oculto y consúltelas en su
~/.bashrc
:Un guión debe sostenerse por sí mismo. Debe tener valor como algo que pueda reutilizarse o utilizarse para más de un propósito.
fuente
.
osource
, un script se ejecuta mediante un proceso bash separado y tiene su propio entorno. Por esta razón, cualquier cosa que modifique el entorno de shell (por ejemplo, funciones, variables, etc.) no persistirá en el entorno de shell desde el que ejecuta el script.Las otras respuestas proporcionan algunas pautas generales suaves basadas en el gusto personal, pero ignoran muchos hechos pertinentes que uno debe considerar al decidir entre guiones, funciones o alias.
Alias y funciones ¹
Guiones
$PATH
búsqueda, muchos shells almacenan un hash de su nombre de ruta en la memoria para ahorrar tiempo en futuras$PATH
búsquedas, pero ese es el alcance de la huella de memoria de un script cuando no está en uso.Las secuencias de comandos se pueden invocar de más formas que las funciones y los alias. Se pueden pasar como argumento a un intérprete, como
sh script
, o invocarse directamente como un ejecutable, en cuyo caso#!/bin/sh
se invoca al intérprete en la línea shebang (por ejemplo ) para ejecutarlo. En ambos casos, el script es ejecutado por un proceso de intérprete separado con su propio entorno separado del de su shell, cuyo entorno el script no puede afectar de ninguna manera. De hecho, el intérprete de shell ni siquiera tiene que coincidir con el shell de invocación. Debido a que los scripts invocados de esta manera parecen comportarse como cualquier ejecutable ordinario, cualquier programa puede usarlos.Por último, un guión puede ser leído y ejecutado por el shell actual con
.
, o en algunos proyectiles,source
. En este caso, el script se comporta como una función que se lee a pedido en lugar de mantenerse constantemente en la memoria.Solicitud
Dado lo anterior, podemos llegar a algunas pautas generales sobre si hacer algo un script o una función / alias.
¿Es necesario que otros programas, además de su shell, puedan usarlo? Si es así, tiene que ser un guión.
¿Solo desea que esté disponible desde un shell interactivo? Es común querer cambiar el comportamiento predeterminado de muchos comandos cuando se ejecutan interactivamente sin afectar los comandos / scripts externos. Para este caso, use un conjunto de alias / funciones en el archivo rc "modo interactivo solamente" del shell (para
bash
esto es.bashrc
).¿Necesita cambiar el entorno del shell? Tanto una función / alias como un script de origen son posibles opciones.
¿Es algo que usas con frecuencia? Probablemente sea más eficiente mantenerlo en la memoria, así que conviértalo en una función / alias si es posible.
Por el contrario, ¿es algo que usas raramente? En ese caso, no tiene sentido tener memoria de memoria cuando no la necesita, así que conviértalo en un script.
¹ Si bien las funciones y los alias tienen algunas diferencias importantes, se agrupan porque las funciones pueden hacer todo lo que pueden hacer los alias. Los alias no pueden tener variables locales ni pueden procesar argumentos, y son inconvenientes para algo más que una línea.
² Cada proceso en ejecución en un sistema Unix tiene un entorno que consiste en un grupo de
variable=value
pares que a menudo contienen configuraciones de configuración global, comoLANG
la configuración regional predeterminada yPATH
para especificar la ruta de búsqueda ejecutable.fuente
alias g='gradle'
autocompletado de Gradle cuando uso mig
alias, pero no lo saco de fábrica cuando uso un scriptgradle $*
o una función congradle $@
Creo que depende del gusto de cada persona. Para mí la lógica es así:
Realmente no hay nada que te impida hacer algo que funcione .
fuente
Al menos parcialmente es una cuestión de gusto personal. Por otro lado, hay algunas distinciones funcionales claras:
En cuanto a las secuencias de comandos de shell que he hecho en los últimos años, he dejado de escribir alias (porque todas tienden a convertirse en funciones con el tiempo) y hago secuencias de comandos solo si necesitan estar disponibles también en entornos que no sean bash.
PD: En
alias command="bash bashscriptname"
realidad, no veo ninguna razón para hacer esto. Incluso sibashscriptname
no está en $ PATH, un simplealias c=/path/to/script
sería suficiente.fuente
alias command="bash bashscriptname"
el script no necesariamente tiene que ser ejecutable; en elalias c=/path/to/script
tiene que hacerlo.exec()
Aquí hay algunos puntos adicionales sobre alias y funciones:
Por ejemplo:
Como podemos ver, hay espacios de nombres separados para alias y funciones; se pueden encontrar más detalles usando
declare -A -p BASH_ALIASES
ydeclare -f f
, que imprime sus definiciones (ambos se almacenan en la memoria).Ejemplo que muestra limitaciones de alias:
Como podemos ver, los alias no son anidables, a diferencia de las funciones. Además, su uso se limita a las sesiones interactivas.
Finalmente, tenga en cuenta que puede tener un cálculo arbitrario en un alias al declarar una función que la llame de inmediato, así:
que ya se usa ampliamente en el caso de los alias de Git. El beneficio de hacerlo sobre la declaración de una función es que su alias no se puede sobrescribir simplemente al generar (o usar
.
) un script que declare una función con el mismo nombre.fuente
Cuándo escribir un guión ...
export
variable y / o función ed se pasan por valor al script. Los cambios en esas variables no se propagan de nuevo al script principal.Cuándo escribir una función ...
Cuando escribir un alias ...
~/.profile
o~/.bashrc
.Dentro de los scripts como los de la biblioteca, a veces se necesita un alias para una función, como cuando se cambia el nombre de una función pero se requiere compatibilidad con versiones anteriores. Esto se puede lograr creando una función simple con el nombre antiguo que pase todos sus argumentos a la nueva función ...
fuente
Otra cosa que no creo que se haya mencionado: una función se ejecuta en el contexto del proceso de invocación, mientras que un script bifurca un nuevo shell.
Esto podría ser importante para el rendimiento: una función es más rápida, ya que no lo hace
fork()
yexec()
. En circunstancias normales, la diferencia es trivial, pero si está depurando un sistema que no tiene memoria y está agitando las páginas, podría hacer una gran diferencia.Además, si desea modificar su entorno actual de shell, debe usar una función. Por ejemplo, una función podría cambiar la búsqueda de comandos
$PATH
para el shell actual, pero un script no puede, porque opera en una copia fork / exec de$PATH
.fuente
export -f
una función, aunque el funcionamiento interno preciso de esto es algo oscuro. Esto no es portátil al shell Bourne tradicional, creo.Script y alias y script y función no son mutuamente excluyentes. Puede almacenar y almacenar alias y funciones en scripts.
Los scripts son solo código que se hace persistente . Las funciones útiles y los alias que le gustaría usar en el futuro se almacenan en scripts. Sin embargo, un script suele ser una colección de más de una función.
Como los alias no están parametrizados , son muy limitados; generalmente para definir algunos parámetros predeterminados.
Una función es una unidad de código separada , un concepto bien definido de unas pocas líneas de código que no pueden separarse en partes más pequeñas y útiles; uno que puede ser reutilizado directamente u otro por otras funciones.
fuente
Si debe ser muy rápido, conviértalo en un alias o una función.
Si debe ser utilizable fuera de su shell preferido, conviértalo en un script. 1
Si toma argumentos, conviértalo en una función o un script.
Si necesita contener caracteres especiales, conviértalo en un alias o una secuencia de comandos. 2
Si necesita trabajar con sudo, conviértalo en un alias o un script. 3
Si desea cambiarlo fácilmente sin cerrar sesión e iniciar sesión, un script es más fácil. 4 4
Notas al pie
1 O conviértalo en un alias, póngalo
~/.env
yexport ENV="$HOME/.env"
configúrelo, pero es complicado hacerlo funcionar de forma portátil.2 Los nombres de funciones deben ser identificadores, por lo que deben comenzar con una letra y solo pueden contener letras, dígitos y guiones bajos. Por ejemplo, tengo un alias
alias +='pushd +1'
. No puede ser una función.3 Y agrega el alias
alias sudo='sudo '
. Lo mismo ocurre con cualquier otro comando comostrace
,gdb
etc., que tome un comando como primer argumento.4 Ver también: fpath. Por supuesto, también puede hacer
source ~/.bashrc
o similar, pero esto a menudo tiene otros efectos secundarios.fuente
+
en bash. Curiosamente, después de probar, descubrí que en bash puedes hacer+
un alias pero no una función, como dices, pero zsh es lo contrario:+
puede ser una función pero no un alias.zsh
tienes que escribiralias -- +='some command here'
.+
sea portátil. Vea la especificación POSIX en nombres de aliassudo
uso. Con respecto a la nota al pie 4, almaceno mis alias~/.bash_aliases
y las definiciones de funciones~/.bash_functions
para poder leerlas fácilmentesource
(sin peligro de efectos secundarios).Solo para agregar algunas notas:
Aparte de eso, podría usar la forma más simple posible, es decir, primero considerar el alias, luego la función, luego el script.
fuente
sudo
. Pero primero lo necesitasalias sudo='sudo '
.Mi regla de oro es:
fuente
En un entorno multiusuario (o multisysamin), uso scripts para todo, incluso si solo termina siendo un breve contenedor 'exec something ....'.
Claro, es técnicamente más lento / menos eficiente que un alias o función, pero eso casi nunca importa, y siempre que esté en la ruta, un script siempre funciona.
Se puede llamar a su función desde cron, desde algo con un entorno reducido o modificado como sudo o env, o el usuario puede estar usando un shell diferente para usted, todo o lo que es probable que rompa un alias o función.
Si tiene algo sensible al rendimiento, maneje eso como un caso especial, o mejor aún, considere que es un disparador para reescribir en un lenguaje de script más funcional.
Si hablamos de características que solo se usarán en otros scripts, entonces también puede considerar definir un shell estándar y escribir un script de biblioteca de funciones que simplemente pueda ser. I fuente a todos los otros guiones.
T
fuente
Un ejemplo de una situación en la que lo más probable es que desee utilizar un alias.
Sé que esta es una publicación antigua, pero me gustaría señalar una situación en la que casi tuve que usar una combinación de alias con un script y elegí no usar una función.
Tengo un script
~/.bin/
llamadosetup
que hace lo siguiente: 1El punto es que si solo corriera
setup <project-name>
, no habría definido esas variables y no habría llegado al directorio en absoluto. La solución que he encontrado para ser el mejor fue la de añadir esta secuencia de comandosPATH
y añadiralias setup=". ~/.bin/setup"
a~/.bashrc
o lo que sea.Notas:
fuente
Cuando escribir un guion
Cuando desee ejecutar el comando desde una herramienta que no sea el shell.
Esto incluye vim (para mí): tener filtros escritos y otros programas como scripts, puedo hacer algo como
:%!my-filter
filtrar un archivo a través del programa desde mi editor.Si
my-filter
fuera una función o un alias, eso no sería posible.fuente