¿Cómo funcionan `>` y `>>`?

9

Intenté revun archivo y luego lo canalicé cat > same_filepero se estaba convirtiendo en un archivo en blanco.

Mientras lo intentaba rev file.txt | cat > file2.txt && mv file.txt file2.txt;funcionó.

Incluso rev file.txt | cat >> file.txt;funcionó.

Pero cuando lo intenté rev file.txt | cat > file.txtfalló.

Vintux
fuente
También puede dejar catfuera de esta manera: rev file.txt > file2.txt && mv file2.txt file.txt. Este es un uso superfluo decat . Al dejarlo afuera, ahorras un proceso adicional.
matega

Respuestas:

19

Lo básico que debe comprender en este caso entre ambas formas de redireccionamiento (> y >>) es:

>

Redirige y sobrescribe la información a la que apuntaba. Esto sucede mientras recibe cualquier información a través de la tubería "|"

>>

Redirecciona y concatena la información a la que fue apuntada. Esto sucede mientras recibe cualquier información a través de la tubería "|"

En ambos casos, si el archivo no existe, se creará en su lugar. Solo en ">>" se concatenará la información si la vuelve a ejecutar en el mismo archivo. Con ">" simplemente sobrescribiría todo lo que hizo en la primera ejecución.

Pero aquí está el trato cuando se usa el mismo archivo de entrada que el archivo de salida. En ese caso particular, si usa ">", estaría eliminando la información que la parte de "entrada" debe analizar, ya que el archivo de salida estaría "sobrescribiéndola". Entonces en:

rev file.txt | cat > file.txt

Lo que realmente sucede en la "explicación en cámara lenta" es:

  1. revse prepara para revertir el contenido file.txty enviarlo a la tubería
  2. Mientras revenvía la información a la tubería, la tubería la transmite directamente a cat.
  3. Mientras catrecibe la información, la aplicará automáticamente a la file.txtque se configuró.
  4. La palabra clave aquí es "while", porque todo está sucediendo al mismo tiempo. Vea los excelentes comentarios a continuación de Emil para tener una comprensión más profunda de esta parte.
  5. catno esperará reva canalizar todo el archivo. Simplemente comenzará en el momento en que llegue la primera parte de la información, lo que significa que, según el símbolo que haya utilizado, abrirá una conexión file.txt.
  6. En este caso, dado que usó > en lugar de >> , el shell truncará el archivo de salida, lo que significa que se abrirá y borrará la información file.txtmientras espera que llegue la nueva información. Con >> abriría una conexión con file.txty esperaría nueva información sobre la última línea detectada.
  7. Dado que la información ya se borró file.txtcon > , revintentaría hacer su trabajo y no obtendría nada porque cateliminó todo en preparación para la nueva información.

Entonces, ¿por qué trabajan los demás después de leer lo anterior? Debido a esto:

rev file.txt | cat > file2.txt && mv file.txt file2.txt

Aquí está conectando a cat que está enviando la información a otro archivo. En este caso, el archivo de entrada procesado file.txtno es el mismo que el archivo de salida file2.txt. Después de eso, literalmente, va a sobrescribir el conjunto file2.txtcon file.txt, por lo que todo el proceso realizado por catfue suprimido. Básicamente, toda la línea podría simplificarse como cp file.txt file2.txtporque está haciendo lo mismo, ya que file2.txtal final pierde revy se sobrescribe con el mvcomando.

rev file.txt | cat >> file.txt

En este caso, está concatenando la información en el mismo archivo. Por lo tanto, solo abre una conexión a ese archivo pero no borra la información como se ve con un solo > . El resultado final debe ser, la información original más la información invertida.

Luis Alvarado
fuente
55
El archivo no está truncado por cat. Se trunca por la carcasa, antes de cualquiera de los comandos de la tubería están incluso empezar.
Emil Jeřábek
Correcto, estaba buscando palabras más fáciles de explicar. Dado que es un poco difícil de explicar si el OP no sabe qué es un shell y todo eso. Tratando de hacerlo lo más "amigable" posible.
Luis Alvarado
1
Bueno, en realidad no importa que lo haga el shell, sino que el momento que presenta es incorrecto. El truncamiento no ocurrirá en el paso 6, pero en el paso 0. rev file.txt | cat --bogus-option > file.txttambién truncará el archivo, aunque cat no intentará abrirlo.
Emil Jeřábek
@ EmilJeřábek tienes razón. Aún así, los usuarios que no saben cómo se comporta lo tendrán más fácil si vamos paso a paso solo con los comandos. Además, su ejemplo sigue enviando la información al mismo archivo, por lo que bash leerá toda esa línea, verá el resultado y seguirá abierto Y truncado. El error es simplemente la salida de stderr a stdout.
Luis Alvarado
44
Vea también moreutils , una fantástica colección de herramientas (disponible en el repositorio de paquetes como moreutils) que incluye sponge, una herramienta diseñada específicamente para el uso de sobrescribir un archivo de entrada. Por ejemplo, la rev file.txt >file2.txt && mv file2.txt file.txtsolución se convertiría rev file.txt | sponge file.txt, lo que funcionará correctamente incluso cuando ya haya algo llamado file2.txt.
Daniel Wagner
9

Cuando el shell ve la redirección, primero abre los archivos relevantes, antes de ejecutar cualquiera de los comandos involucrados. Por lo tanto, cuando haces:

foo file.txt | bar > file.txt

La redirección a file.txthace que se trunca antes de foo ejecutarse y poder leerse file.txt. En una nota al margen, esta es la razón por la que no puede hacer:

sed 'blah' file.txt > file.txt

Y por qué sedtiene una opción de edición en el lugar.

Por último, haciendo:

.. | cat > file.txt

es un uso inútil del gato , especialmente si está intentando leer desde el file.txtprincipio.

Si desea revertir un archivo en el lugar, no hay atajos . Es posible que pueda usar los trucos sedo awkcon la edición en el lugar.

muru
fuente
3

>es un redirector (operador) que envía la salida a otra cosa
(entrada del siguiente comando, impresora ...)

En su caso, la salida va a un archivo file.txt, si este archivo ya existe se sobrescribe, si no se crea.

>>es un operador de agregar, si file.txtya existe, la salida se agrega al final del archivo. si el archivo no existe, se crea y la salida se escribe en el nuevo archivo, igual que >(redirector).

Ken Mollerup
fuente
El OP parece haber entendido esto. La confusión parece provenir solo del mismo archivo que está en ambos lados de los operadores >y >>.
bzlm
0

Puede usar Vim en modo Ex:

ex -sc '%!rev' -cx file.txt
  1. % seleccione todas las líneas

  2. ! ejecutar comando

  3. x guardar y cerrar

Steven Penny
fuente