¿Cómo ejecuto múltiples comandos usando el mismo argumento?


16

Me pregunto si es posible realizar acciones en cadena en la terminal de Ubuntu como:

action 1 on objectA . then action 2 on objectA 

sin tener que repetir el nombre del objeto A nunca más.

Ejemplo:

touch file.js && openEditor "$1" 

o algo así.


Hay muchas formas de hacerlo, pero depende de tus necesidades. ¿Qué es el objeto A? un archivo ? ¿De qué acciones estamos hablando?
Sergiy Kolodyazhnyy

gracias, generalmente un archivo efectivo, también puede ser una carpeta
HoCo_

3
Aquí, &enviará el comando "táctil" al fondo. Si tenía la intención de "abrir el editor si el toque fue exitoso", entonces quiere en su &&lugar
glenn jackman

¿Por qué te encuentras con esta publicación? Ya tienes muchas respuestas e incluso aceptaste una.
muru

Respuestas:


27

Con bash History Expansion , puede referirse a la enésima palabra de la línea de comando actual usando, !#:npor ejemplo,

$ touch foobar && ls -l !#:1
touch foobar && ls -l foobar
-rw-rw---- 1 steeldriver steeldriver 0 Jun 20 14:54 foobar

$ touch foo bar && ls -l !#:2
touch foo bar && ls -l bar
-rw-rw-r-- 1 steeldriver steeldriver 12 Jun 20 14:58 bar

¿Puedo preguntar qué versión de bash estás usando?
Sergiy Kolodyazhnyy

@SergiyKolodyazhnyy esto esGNU bash, version 4.3.48(1)-release
steeldriver

55
también puede designar un rango de palabras :touch foo bar && ls -l !#:1-2
glenn jackman

1
@HoCo_, el !personaje introduce una expresión de expansión de historial cuando se encuentra en un shell interactivo : está destinado a la manipulación de la línea de comandos sobre la marcha mientras escribe, y está deshabilitado dentro de scripts no interactivos
steeldriver

1
@HoCo_ en un script, debe saber cuál es el argumento con anticipación, por lo que, por ejemplo, podría hacerloarg1=file.js; touch "$arg1" && openEditor "$arg1"
steeldriver el

12

Hay un atajo útil para un caso de uso común. En tu ejemplo estás haciendo:

$ touch file.js
$ openEditor <alt>+<.>

En el segundo comando, el truco es escribir openEditor(con un espacio después) seguido de Alt+ .. Esto insertará el último argumento del último comando, que es file.js. (Si Altpor alguna razón no funciona , Escdebería funcionar también).

Dado que a menudo el "objeto" es el último argumento del comando anterior, esto se puede usar con frecuencia. Es fácil de recordar y se integrará rápidamente en su conjunto de accesos directos de shell utilizados intuitivamente.

Hay muchas cosas que puedes hacer con esto, aquí hay un artículo detallado sobre las posibilidades: /programming/4009412/how-to-use-arguments-from-previous-command .

Como beneficio adicional, esto funcionará no solo en bash sino en todos los programas que usan libreadline para procesar la entrada de la línea de comandos.


2
Esto se puede combinar con un argumento de dígitos , por ejemplo, para obtener el segundo argumento de retención Alty presione 2.(o Esc, 2, Esc, .), para obtener el segundo al último argumento de prensa Alt+ -, el tipo 2y pulse Alt+ .(o Esc, -2, Esc, .).
postre

@dessert ¿Qué sucede si ejecuto quiero más de uno de los argumentos? Por ejemplo, corro echo 1 2 3 4entonces quiero 2y 3para el próximo comando
wjandrea

@dessert ¡Lo encontré yo mismo! Solo necesita escribir algo más entre ellos, como un espacio. Para concatenarlos, la forma más fácil es escribir un espacio y luego retroceder.
wjandrea

1
asimiento @wjandrea Alty el tipo 2., presione la barra espaciadora, bodega Alty tipo 3.- si quieres un rango, el uso de expansión de historia: !!:2-3.
postre

9

En lo que respecta al shell interactivo predeterminado bashy al shell de secuencias de comandos dash, puede usar $_para recuperar el último argumento del último comando .

$ echo "Hello World"; echo same "$_"
Hello World
same Hello World

csh y tcsh tienen referencias de historial, específicamente para la última palabra del comando, puede usar !$, y para argumentos individuales !:<index>:

~% echo foo bar
foo bar
~% echo !$
echo bar
bar

% echo bar baz
bar baz
% echo !:1
echo bar
bar

En general, es mejor asignar lo que sea objectAa una variable y usarlo en múltiples comandos, bucles, etc. Alternativamente, una función podría ser una opción:

$ foo(){ echo "$@"; stat --print="%F\n" "$@";}
$ foo testdir
testdir
directory

1
Solo me gustaría señalar que $_funciona de manera ligeramente diferente a !#:ncomo se expande este último antes de guardar el comando en la historia. Por lo tanto, retroceder en la historia aún mostraría el comando con $_while, !#:nque habría sido reemplazado por su valor real. Ambos tienen pros y contras.
Dan

3
Además, como de costumbre, $_debe citarse, ya que de lo contrario se divide y se pega como todo lo demás. (Simplemente no lo vemos aquí ya que echoune sus argumentos con un solo espacio). Pero, por ejemplo touch "hello there"; ls -l $_ , no funcionará.
ilkkachu

1
@Dan Creo que el mayor profesional $_es que es portátil. Después de todo, !#:nes específico de bash.
Sergiy Kolodyazhnyy

3

Recomendaría contra el enfoque de historia dado en la respuesta de steeldriver . Esto depende del estado global, que siempre es frágil.

Lo mejor es realizar un bucle inicial sobre todos los comandos necesarios, utilizando una variabe adecuada:

$ for c in touch gedit; do $c foo.txt; done

Lo que es un problema en general es que Bash no aborta cuando hay una falla, es decir, esto en realidad se comporta en touch foo.txt; gedit foo.txtlugar de encadenarse &&. Entonces, para estar seguro, puede agregar un break:

$ for c in touch gedit; do $c foo.txt || break; done

1

Cuando cocino una línea, a veces asigno mis cosas repetidas a una variable de shell que uso varias veces en el comando. Puedo recuperarlo y editarlo para usar un argumento diferente con flecha hacia arriba, control + a, control + flecha hacia la derecha para acercar el cursor al t=.

t=testloop; asm-link -d "$t.asm" && perf stat -r2 ./"$t"

Tenga en cuenta que esto facilita agregar una extensión o una variación en el nombre.

También tenga en cuenta que necesito una ;asignación posterior a la variable, porque var=value cmdsolo la establece como una variable de entorno para ese comando, y no afecta el contexto de shell.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.