bash - script - Ejecutando múltiples comandos en una línea en shell
scripts linux ejercicios resueltos (6)
¿Por qué no cp
a la ubicación 1, luego mv
a la ubicación 2. Esto se encarga de "quitar" 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 inicie el siguiente, entonces usaría &&
lugar:
cp file1 file2 && cp file1 file3 && rm file1
De esa manera, si alguno de los comandos cp
falla, el rm
no se ejecutará.
Digamos que tengo un archivo /templates/apple
y quiero
- ponerlo en dos lugares diferentes y luego
- quitar el original
Entonces, /templates/apple
se copiará a /templates/used
AND /templates/inuse
y luego me gustaría quitar el original.
¿Es cp
la 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í como:
cp /templates/apple /templates/used | cp /templates/apple /templates/inuse | rm /templates/apple
¿Es esta la sintaxis correcta?
Estas usando |
(pipe) para dirigir la salida de un comando a otro comando. Lo que está buscando es un operador &&
para ejecutar 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 (de manera no exhaustiva) los operadores / separadores de comandos de bash:
-
|
canaliza (tuberías) la salida estándar (stdout
) de un comando en la entrada estándar de otro. Tenga en cuenta questderr
todavía va a su destino predeterminado, sea lo que sea. -
|&
canaliza tantostdout
comostderr
de un comando en la entrada estándar de otro. Muy útil, disponible en la versión 4 y superior de bash. -
&&
ejecuta el comando de la derecha de&&
solo si el anterior tuvo éxito. -
||
ejecuta el comando de la derecha de||
Sólo que el anterior falló. -
;
ejecuta el comando de la mano derecha de;
siempre sin importar si el comando anterior tuvo éxito o falló. A menosset -e
se haya invocadoset -e
previamente, lo que hace quebash
falle en un error.
Otra opción es escribir Ctrl + V Ctrl + J al final de cada comando.
Ejemplo (reemplace #
con Ctrl + V Ctrl + J ):
$ echo 1#
echo 2#
echo 3
Salida:
1
2
3
Esto ejecutará los comandos sin importar si los anteriores fallaron.
Igual que: echo 1; echo 2; echo 3
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 (reemplace #
con Ctrl + V Ctrl + J ):
$ echo 1 &&#
failed-command &&#
echo 2
Salida:
1
failed-command: command not found
En zsh
también puede usar Alt + Intro o Esc + Intro en lugar de Ctrl + V Ctrl + J
Prueba esto..
cp /templates/apple /templates/used && cp /templates/apple /templates/inuse && rm /templates/apple
Tenga en cuenta que cp AB; rm A
cp AB; rm A
es exactamente mv AB
. También será más rápido, ya que no tiene que copiar realmente los bytes (suponiendo que el destino se encuentra en el mismo sistema de archivos), simplemente cambie el nombre del archivo. Así que quieres cp AB; mv AC
cp AB; mv AC
Usar tuberías me parece raro. De todos modos debes usar el operador lógico and
Bash:
$ cp /templates/apple /templates/used && cp /templates/apple /templates/inuse && rm /templates/apples
Si los comandos de cp
fallan, no se ejecutará el rm
.
O bien, puede hacer una línea de comandos más elaborada utilizando un bucle for
y cmp
.