Solución:
Estos se llaman operadores de shell y sí, hay más de ellos. Daré una breve descripción de los más comunes entre las dos clases principales, los operadores de control y los operadores de redirección, y cómo funcionan con respecto al shell bash.
A. Operadores de control
Definición de POSIX
En el lenguaje de comandos de shell, un token que realiza una función de control.
Es uno de los siguientes símbolos:& && ( ) ; ;;
| ||
Y |&
en bash.
A !
es no un operador de control pero una palabra reservada. Se convierte en un NO lógico [negation operator] dentro de Expresiones aritméticas y construcciones de prueba internas (aunque todavía requiere un delimitador de espacio).
A.1 Lista de terminadores
-
;
: Ejecutará un comando después de que otro haya terminado, independientemente del resultado del primero.command1 ; command2
Primero
command1
se ejecuta, en primer plano, y una vez finalizado,command2
se ejecutará.Una nueva línea que no está en un literal de cadena o después de ciertas palabras clave es no equivalente al operador de punto y coma. Una lista de
;
comandos simples delimitados sigue siendo un lista – como en el analizador de shell, aún debe continuar leyendo en los comandos simples que siguen a un;
comando simple delimitado antes de ejecutarlo, mientras que una nueva línea puede delimitar una lista completa de comandos, o una lista de listas. La diferencia es sutil, pero complicada: dado que el shell no tiene un imperativo previo para leer datos después de una nueva línea, la nueva línea marca un punto en el que el shell puede comenzar a evaluar los comandos simples que ya ha leído, mientras que un;
el punto y coma no lo hace. -
&
: Esto ejecutará un comando en segundo plano, lo que le permitirá continuar trabajando en el mismo shell.command1 & command2
Aquí,
command1
se inicia en segundo plano ycommand2
comienza a correr en primer plano inmediatamente, sin esperarcommand1
salir.Una nueva línea después
command1
es opcional.
A.2 Operadores lógicos
-
&&
: Se utiliza para crear listas Y, le permite ejecutar un comando solo si otro salió con éxito.command1 && command2
Aquí,
command2
correrá despuéscommand1
ha terminado y solamente sicommand1
tuvo éxito (si su código de salida era 0). Ambos comandos se ejecutan en primer plano.Este comando también se puede escribir
if command1 then command2 else false fi
o simplemente
if command1; then command2; fi
si se ignora el estado de devolución. -
||
: Se utiliza para crear listas OR, le permite ejecutar un comando solo si otro salió sin éxito.command1 || command2
Aquí,
command2
solo se ejecutará sicommand1
falló (si devolvió un estado de salida distinto de 0). Ambos comandos se ejecutan en primer plano.Este comando también se puede escribir
if command1 then true else command2 fi
o de una manera más corta
if ! command1; then command2; fi
.Tenga en cuenta que
&&
y||
son asociativos por la izquierda; ver Prioridad de los operadores lógicos de shell &&, || para más información. -
!
: Esta es una palabra reservada que actúa como el operador “no” (pero debe tener un delimitador), que se utiliza para negar el estado de retorno de un comando; devuelve 0 si el comando devuelve un estado distinto de cero, devuelve 1 si devuelve el estado 0 . También un NO lógico para eltest
utilidad.! command1 [ ! a = a ]
Y un verdadero operador NOT dentro de Expresiones aritméticas:
$ echo $((!0)) $((!23)) 1 0
A.3 Operador de tubería
-
|
: El operador de tubería, pasa la salida de un comando como entrada a otro. Un comando creado a partir del operador de tubería se denomina tubería.command1 | command2
Cualquier salida impresa por
command1
se pasa como entrada acommand2
. -
|&
: Esta es una abreviatura de2>&1 |
en bash y zsh. Pasa tanto la salida estándar como el error estándar de un comando como entrada a otro.command1 |& command2
A.4 Otra puntuación de la lista
;;
se utiliza únicamente para marcar el final de una declaración de caso. Ksh, bash y zsh también son compatibles ;&
pasar al siguiente caso y ;;&
(no en ATT ksh) para continuar y probar los casos posteriores.
(
y )
se utilizan para agrupar comandos y ejecutarlos en una subcapa. y
también grupos de comandos, pero no los inicie en un subshell. Vea esta respuesta para una discusión de los diversos tipos de paréntesis, corchetes y llaves en la sintaxis de shell.
B. Operadores de redireccionamiento
Definición de POSIX de operador de redirección
En el lenguaje de comandos de shell, un token que realiza una función de redirección. Es uno de los siguientes símbolos:
< > >| << >> <& >& <<- <>
Estos le permiten controlar la entrada y salida de sus comandos. Pueden aparecer en cualquier lugar dentro de un comando simple o pueden seguir un comando. Las redirecciones se procesan en el orden en que aparecen, de izquierda a derecha.
-
<
: Da entrada a un comando.command < file.txt
Lo anterior se ejecutará
command
sobre el contenido defile.txt
. -
<>
: igual que arriba, pero el archivo está abierto en leer + escribir modo en lugar de solo lectura:command <> file.txt
Si el archivo no existe, se creará.
Ese operador rara vez se usa porque los comandos generalmente solo leer de su stdin, aunque puede resultar útil en una serie de situaciones específicas.
-
>
: Dirige la salida de un comando a un archivo.command > out.txt
Lo anterior guardará la salida de
command
comoout.txt
. Si el archivo existe, se sobrescribirá su contenido y si no existe se creará.Este operador también se usa a menudo para elegir si algo debe imprimirse con un error estándar o una salida estándar:
command >out.txt 2>error.txt
En el ejemplo anterior,
>
redirigirá la salida estándar y2>
redirecciona el error estándar. La salida también se puede redirigir usando1>
pero, dado que este es el valor predeterminado,1
generalmente se omite y se escribe simplemente como>
.Entonces, para correr
command
sobrefile.txt
y guarde su salida enout.txt
y cualquier mensaje de error enerror.txt
correría:command < file.txt > out.txt 2> error.txt
-
>|
: Hace lo mismo que>
, pero sobrescribirá el destino, incluso si el shell se ha configurado para rechazar la sobrescritura (conset -C
oset -o noclobber
).command >| out.txt
Si
out.txt
existe, la salida decommand
reemplazará su contenido. Si no existe, se creará. -
>>
: Hace lo mismo que>
, excepto que si el archivo de destino existe, se añaden los nuevos datos.command >> out.txt
Si
out.txt
existe, la salida decommand
se agregará a él, después de lo que ya esté en él. Si no existe, se creará. -
>&
: (según la especificación POSIX) cuando está rodeado por digitos (1>&2
) o-
en el lado derecho (1>&-
) ya sea solo redirecciona uno descriptor de archivo o lo cierra (>&-
).A
>&
seguido de un número de descriptor de archivo es una forma portátil de redirigir un descriptor de archivo, y>&-
es una forma portátil de cerrar un descriptor de archivo.Si el lado derecho de esta redirección es un archivo, lea la siguiente entrada.
-
>&
,&>
,>>&
y&>>
: (lea también arriba) Redirigir tanto el error estándar como la salida estándar, reemplazando o agregando, respectivamente.command &> out.txt
Tanto el error estándar como la salida estándar de
command
será guardado enout.txt
, sobrescribiendo su contenido o creándolo si no existe.command &>> out.txt
Como arriba, excepto que si
out.txt
existe, la salida y el error decommand
se le agregará.los
&>
variante se origina enbash
, mientras que la>&
La variante proviene de csh (décadas antes). Ambos entran en conflicto con otros operadores de shell POSIX y no deben usarse en dispositivos portátiles.sh
guiones. -
<<
: Un documento aquí. A menudo se utiliza para imprimir cadenas de varias líneas.command << WORD Text WORD
Aquí,
command
tomará todo hasta que encuentre la próxima aparición deWORD
,Text
en el ejemplo anterior, como entrada. TiempoWORD
es seguidoEoF
o variaciones de los mismos, puede ser cualquier cadena alfanumérica (y no solo) que desee. CuandoWORD
se cita, el texto del documento aquí se trata literalmente y no se realizan ampliaciones (en variables, por ejemplo). Si no está entre comillas, las variables se expandirán. Para obtener más detalles, consulte el manual de bash.Si desea canalizar la salida de
command << WORD ... WORD
directamente en otro comando o comandos, debe poner la tubería en la misma línea que<< WORD
, no puede ponerlo después de la PALABRA de terminación o en la línea siguiente. Por ejemplo:command << WORD | command2 | command3... Text WORD
-
<<<
: Aquí cadenas, similares a aquí documentos, pero destinadas a una sola línea. Estos existen solo en el puerto Unix o rc (donde se originó), zsh, algunas implementaciones de ksh, yash y bash.command <<< WORD
Todo lo que se da como
WORD
se expande y su valor se pasa como entrada acommand
. Esto se usa a menudo para pasar el contenido de las variables como entrada a un comando. Por ejemplo:$ foo="bar" $ sed 's/a/A/' <<< "$foo" bAr # as a short-cut for the standard: $ printf '%sn' "$foo" | sed 's/a/A/' bAr # or sed 's/a/A/' << EOF $foo EOF
Algunos otros operadores (>&-
, x>&y
x<&y
) se puede utilizar para cerrar o duplicar descriptores de archivos. Para obtener detalles sobre ellos, consulte la sección correspondiente del manual de su shell (aquí, por ejemplo, para bash).
Eso solo cubre los operadores más comunes de conchas tipo Bourne. Algunos shells tienen algunos operadores de redirección adicionales propios.
Ksh, bash y zsh también tienen construcciones <(…)
, >(…)
y =(…)
(ese último en zsh
solamente). No se trata de redirecciones, sino de sustitución de procesos.
Advertencia sobre '>'
Los principiantes de Unix que acaban de aprender sobre la redirección de E / S (<
y >
) a menudo intenta cosas como
command … input_file > the_same_file
o
command … < file > the_same_file
o, casi de manera equivalente,
cat file | command … > the_same_file
(grep
, sed
, cut
, sort
, y spell
son ejemplos de comandos que la gente se siente tentada a usar en construcciones como estas). Los usuarios se sorprenden al descubrir que estos escenarios dan como resultado que el archivo se vacíe.
Un matiz que no parece mencionarse en la otra respuesta se puede encontrar acechando en la primera oración de la Redirección sección de bash (1):
Antes de que se ejecute un comando, su entrada y salida pueden ser redirigido
utilizando una notación especial interpretada por el shell.
Las primeras cinco palabras deben estar en negrita, cursiva, subrayadas, ampliadas, parpadeando, coloreadas en rojo y marcadas con un
antes de que se ejecute el comando. Y recuerda tambien
La redirección de la salida hace que el archivo… se abra para escritura…. Si el archivo no existe, se crea; si existe, se trunca a tamaño cero.
-
Entonces, en este ejemplo:
sort roster > roster
el caparazón abre el
roster
archivo para escribir, truncándolo (es decir, descartando todo su contenido), antes de lasort
el programa comienza a ejecutarse. Naturalmente, no se puede hacer nada para recuperar los datos. -
Uno podría esperar ingenuamente que
tr "[:upper:]" "[:lower:]" < poem > poem
podría ser mejor. Debido a que el shell maneja las redirecciones de izquierda a derecha, se abre
poem
para leer (paratr
entrada estándar) antes de que se abra para escribir (para salida estándar). Pero eso no ayuda. Aunque esta secuencia de operaciones produce dos identificadores de archivo, ambos apuntan al mismo archivo. Cuando el shell abre el archivo para su lectura, el contenido todavía está allí, pero todavía se golpea antes de que se ejecute el programa.
Entonces, ¿qué hacer al respecto?
Las soluciones incluyen:
-
Compruebe si el programa que está ejecutando tiene su propia capacidad interna para especificar a dónde va la salida. Esto a menudo se indica mediante un
-o
(o--output=
) token. En particular,sort -o roster roster
es aproximadamente equivalente a
sort roster > roster
excepto, en el primer caso, el
sort
programa abre el archivo de salida. Y es lo suficientemente inteligente como para no abrir el archivo de salida hasta después ha leído todos los archivos de entrada.Del mismo modo, al menos algunas versiones de
sed
tener un-i
(editar In lugar) opción que se puede utilizar para volver a escribir la salida en el archivo de entrada (de nuevo, después se han leído todas las entradas). A los editores les gustaed
/ex
,emacs
,pico
, yvi
/vim
Permitir al usuario editar un archivo de texto y guardar el texto editado en el archivo original. Tenga en cuenta queed
(al menos) se puede utilizar de forma no interactiva.vi
tiene una característica relacionada. Si escribe:%!command
Ingresar, escribirá el contenido del búfer de edición encommand
, lea la salida e insértela en el búfer (reemplazando el contenido original).
-
Simple pero efectivo:
command … input_file > temp_file && mv temp_fileinput_file
Esto tiene el inconveniente de que, si
input_file
es un enlace, (probablemente) será reemplazado por un archivo separado. Además, el nuevo archivo será de su propiedad, con protecciones predeterminadas. En particular, esto conlleva el riesgo de que el archivo termine siendo legible por todo el mundo, incluso si el originalinput_file
no lo era.Variaciones:
command … input_file > temp_file && cp temp_fileinput_file && rm temp_file
que todavía (potencialmente) dejará el
temp_file
legible en todo el mundo. Aun mejor:cp input_filetemp_file && command … temp_file > input_file && rm temp_file
Estos conservan el estado del enlace, el propietario y el modo (protección) del archivo, potencialmente a costa del doble de E / S. (Es posible que deba utilizar una opción como
-a
o-p
sobrecp
para decirle que conserve los atributos).command … input_file > temp_file &&
cp --attributes-only --preserve=all input_filetemp_file &&
mv temp_fileinput_file
(dividido en líneas separadas solo para facilitar la lectura) Esto conserva el modo del archivo (y, si es root, el propietario), pero lo convierte en propiedad suya (si no es root), y lo convierte en un nuevo, archivo separado.
-
Este blog (edición de archivos "in situ") sugiere y explica
rm input_file && command … > input_file; < input_file
Esto requiere que el
command
Ser capaz de procesar la entrada estándar (pero casi todos los filtros pueden). El blog en sí mismo llama a esto una tontería arriesgada y desaconseja su uso. Y esto también creará un nuevo archivo separado (no vinculado a nada), de su propiedad y con permisos predeterminados. -
El paquete moreutils tiene un comando llamado
sponge
:command … input_file | sponge the_same_file
Consulte esta respuesta para obtener más información.
Aquí hay algo que me sorprendió por completo: error de sintaxis dice:
[Most of these solutions] fallará en un sistema de archivos de solo lectura, donde "solo lectura" significa que su
$HOME
voluntad ser escribible, pero/tmp
estarán solo lectura (por defecto). Por ejemplo, si tiene Ubuntu y ha iniciado en la Consola de recuperación, este suele ser el caso. Además, el operador here-document<<<
tampoco funcionará allí, ya que requiere/tmp
ser leer escribir
porque también escribirá un archivo temporal allí.
(cf. esta pregunta incluye unstrace
'd salida)
Lo siguiente puede funcionar en ese caso:
- Solo para usuarios avanzados:
Si se garantiza que su comando producirá la misma cantidad de datos de salida que de entrada (por ejemplo,sort
, otr
sin los-d
o-s
opción), puedes probarcommand … input_file | dd of=the_same_file conv=notrunc
Consulte esta respuesta y esta respuesta para obtener más información, incluida una explicación de lo anterior, y alternativas que funcionan si se garantiza que su comando producirá la misma cantidad de datos de salida que de entrada. o menos (p.ej,
grep
, ocut
). Estas respuestas tienen la ventaja de que no requieren ningún espacio libre (o requieren muy poco). Las respuestas de arriba del formulario
command … input_file > temp_file && …
requieren claramente que haya suficiente espacio libre para que el sistema pueda contener todo el archivo de entrada (antiguo) y el archivo de salida (nuevo) simultáneamente; esto no es obviamente cierto para la mayoría de las otras soluciones (por ejemplo,sed -i
ysponge
) así como. Excepción:sort … | dd …
probablemente requerirá mucho espacio libre, porquesort
necesita leer toda su entrada antes de que pueda escribir cualquier salida, y probablemente almacena la mayoría, si no todos, de esos datos en un archivo temporal. - Solo para usuarios avanzados:
command … input_file 1<> the_same_file
puede ser equivalente a la
dd
respuesta, arriba. losn<>file
la sintaxis abre el archivo con nombre en el descriptor de archivon
tanto para entrada como para salida, sin truncarlo, una especie de combinación den<
yn>
. Nota: algunos programas (p. Ej.,cat
ygrep
) pueden negarse a ejecutarse en este escenario porque pueden detectar que la entrada y la salida son el mismo archivo. Vea esta respuesta para una discusión de lo anterior, y un script que hace que esta respuesta funcione si se garantiza que su comando producirá la misma cantidad de datos de salida que de entrada o menos.
Advertencia: no he probado el guión de Peter, así que no respondo por él.
¿Entonces, cuál era la pregunta?
Este ha sido un tema popular en U&L; se aborda en las siguientes preguntas:
- ¿Hay alguna forma de modificar un archivo en el lugar?
- Como puedo hacer
iconv
reemplazar el archivo de entrada con la salida convertida? - ¿Por qué el comando
shuf file > file
dejar un archivo vacío? - ¿Puedo leer y escribir en el mismo archivo en Linux sin sobrescribirlo?
- Redirigir al mismo archivo que el archivo de origen procesado por el comando
- ¿Por qué esto
sort
comando dame un archivo vacío? - Redireccionando
tr
stdout a un archivo - grep: el archivo de entrada 'X' también es la salida
- ¿Los operadores de redirección abren descriptores de archivos en paralelo?
- La redirección no sobrescribe el archivo, sino que solo produce uno en blanco
… Y eso sin contar Superusuario o Ask Ubuntu. He incorporado mucha información de las respuestas a las preguntas anteriores aquí en esta respuesta, pero no toda. (Es decir, para obtener más información, lea las preguntas mencionadas anteriormente y sus respuestas).
PD tengo no afiliación con el blog que he citado anteriormente.
Más observaciones sobre ;
, &
, (
y )
-
Tenga en cuenta que algunos de los comandos en la respuesta de terdon pueden ser nulos. Por ejemplo, puedes decir
command1 ;
(sin
command2
). Esto es equivalente acommand1
(es decir, simplemente se ejecuta
command1
en primer plano y espera a que se complete. Comparablemente,command1 &
(sin
command2
) pondrá en marchacommand1
en segundo plano y luego emita otro indicador de shell inmediatamente. -
Por el contrario,
command1 &&
,command1 ||
, ycommand1 |
no tiene ningún sentido. Si escribe uno de estos, el shell (probablemente) asumirá que el comando continúa en otra línea. Mostrará el indicador de shell secundario (continuación), que normalmente se establece en>
y sigue leyendo. En un script de shell, simplemente leerá la siguiente línea y la agregará a lo que ya ha leído. (Cuidado: puede que esto no sea lo que quieres que suceda).Nota: algunas versiones de algunos shells pueden tratar tales comandos incompletos como errores. En tales casos (o, de hecho, en alguna caso en el que tenga un comando largo), puede poner una barra invertida (
) al final de una línea para decirle al shell que continúe leyendo el comando en otra línea:
command1 && command2
o
find starting-directory -mindepth 3 -maxdepth 5 -iname "*.some_extension" -type f -newer some_existing_file -user fred -readable -print
-
Como dice terdon,
(
y)
se puede utilizar para agrupar comandos. La afirmación de que "no son realmente relevantes" para esa discusión es discutible. Algunos de los comandos en la respuesta de terdon pueden ser command grupos. Por ejemplo,( command1 ; command2 ) && ( command3; command4 )
Haz esto:
- Correr
command1
y espera a que termine. - Luego, independientemente del resultado de ejecutar ese primer comando, ejecute
command2
y espera a que termine. -
Entonces sí
command2
tuvo éxito,- Correr
command3
y espera a que termine. - Luego, independientemente del resultado de ejecutar ese comando, ejecute
command4
y espera a que termine.
Si
command2
falló, deje de procesar la línea de comando. - Correr
- Correr
-
Fuera de paréntesis,
|
se une muy fuerte, por lo quecommand1 | command2 || command3
es equivalente a
( command1 | command2 ) || command3
y
&&
y||
atar más fuerte que;
, asi quecommand1 && command2 ; command3
es equivalente a
( command1 && command2 ) ; command3
es decir,
command3
se ejecutará independientemente del estado de salida decommand1
y / ocommand2
.
Reseñas y puntuaciones
Si te animas, tienes la libertad de dejar una crónica acerca de qué te ha gustado de esta sección.