Ejecutar múltiples comandos en una línea en shell

388

Digamos que tengo un archivo /templates/appley quiero

  1. ponlo en dos lugares diferentes y luego
  2. quitar el original

Por lo tanto, /templates/applese copiará a /templates/usedAND /templates/inuse y luego me gustaría eliminar el original.

¿Es cpla mejor manera de hacer esto, seguido de rm? ¿O hay un mejor camino?

Quiero hacerlo todo en una línea, así que estoy pensando que se vería algo así:

cp /templates/apple /templates/used | cp /templates/apple /templates/inuse | rm /templates/apple

¿Es esta la sintaxis correcta?

John Redyns
fuente

Respuestas:

793

Estás utilizando |(pipe) para dirigir la salida de un comando a otro comando. Lo que está buscando es que el &&operador ejecute el siguiente comando solo si el anterior tuvo éxito:

cp /templates/apple /templates/used && cp /templates/apple /templates/inuse && rm /templates/apple

O

cp /templates/apple /templates/used && mv /templates/apple /templates/inuse

Para resumir (no exhaustivamente) los operadores / separadores de comandos de bash:

  • |canaliza (canaliza) la salida estándar ( stdout) de un comando en la entrada estándar de otro. Tenga en cuenta que stderrtodavía entra en su destino predeterminado, sea lo que sea.
  • |&canaliza ambos stdouty stderrde un comando en la entrada estándar de otro. Muy útil, disponible en bash versión 4 y superior.
  • &&ejecuta el comando de la mano derecha &&solo si el anterior tuvo éxito.
  • ||ejecuta el comando de la mano derecha ||solo si el anterior falló.
  • ;ejecuta el comando derecho de ;siempre independientemente de si el comando anterior tuvo éxito o no. A menos que set -ese haya invocado previamente, lo que hace bashque falle un error.
Maxim Egorushkin
fuente
66
Votado Documentación oficial gnu.org/software/bash/manual/bash.html#Lists
flow2k
78

¿Por qué no cpa la ubicación 1, luego mva la ubicación 2. Esto se encarga de "eliminar" el original.

Y no, no es la sintaxis correcta. |se utiliza para "canalizar" la salida de un programa y convertirla en entrada para el siguiente programa. Lo que quieres es ;, que separa múltiples comandos.

cp file1 file2 ; cp file1 file3 ; rm file1

Si necesita que los comandos individuales DEBEN tener éxito antes de que se pueda iniciar el siguiente, entonces usaría &&en su lugar:

cp file1 file2 && cp file1 file3 && rm file1

De esa manera, si alguno de los cpcomandos falla, rmno se ejecutará.

Marc B
fuente
10

Tenga en cuenta que cp A B; rm Aes exactamente mv A B. También será más rápido, ya que no tiene que copiar los bytes (suponiendo que el destino esté en el mismo sistema de archivos), simplemente cambie el nombre del archivo. Entonces quierescp A B; mv A C

Glenn Jackman
fuente
7

Otra opción es escribir Ctrl+V Ctrl+Jal final de cada comando.

Ejemplo (reemplazar #con Ctrl+V Ctrl+J):

$ echo 1#
echo 2#
echo 3

Salida:

1
2
3

Esto ejecutará los comandos independientemente de si los anteriores fallaron.

Igual que: echo 1; echo 2; echo 3

Si desea detener la ejecución de comandos fallidos, agregue &&al final de cada línea excepto la última.

Ejemplo (reemplazar #con Ctrl+V Ctrl+J):

$ echo 1 &&#
failed-command &&#
echo 2

Salida:

1
failed-command: command not found

En zshtambién puede usar Alt+Entero en Esc+Enterlugar deCtrl+V Ctrl+J

Eyal Levin
fuente
3

Prueba esto..

cp /templates/apple /templates/used && cp /templates/apple /templates/inuse && rm /templates/apple

Peter
fuente
2

Usar tuberías me parece extraño. De todos modos, debe usar el andoperador lógico Bash:

$ cp /templates/apple /templates/used && cp /templates/apple /templates/inuse && rm /templates/apples

Si los cpcomandos fallan, rmno se ejecutará.

O bien, puede hacer una línea de comando más elaborada usando un forbucle y cmp.

Renaud
fuente