Para ampliar la respuesta de @Alex Gitelman:sí, hay una diferencia entre "entrada estándar" y la línea de comando.
Cuando escribes rm a.txt b.txt c.txt
, los archivos que enumeras después de rm
se conocen como argumentos y están disponibles para rm a través de una variable especial (llamada argv
internamente). La entrada estándar, por otro lado, se parece a un programa Unix como un archivo llamado stdin
. Un programa puede leer datos de este "archivo" tal como lo haría si abriera un archivo normal en el disco y leyera desde allí.
rm
, como muchos otros programas, toma sus argumentos de la línea de comando pero ignora la entrada estándar. Puedes canalizar lo que quieras; simplemente tirará esos datos. Ahí es donde xargs
Viene muy bien. Lee líneas en la entrada estándar y las convierte en argumentos de línea de comandos, por lo que puede canalizar datos de manera efectiva a la línea de comandos de otro programa. Es un buen truco.
Por ejemplo:
find . -name ".txt" | xargs rm
find . -name ".txt" | grep "foo" | xargs rm
Tenga en cuenta que esto funcionará incorrectamente si hay algún nombre de archivo que contenga líneas nuevas o espacios. Para tratar con nombres de archivos que contengan líneas nuevas o espacios, debe usar en su lugar:
find . -name ".txt" -print0 | xargs -0 rm
Esto le dirá a find
para terminar los resultados con un carácter nulo en lugar de una nueva línea. Sin embargo, grep
no funcionará como antes entonces. En su lugar, usa esto:
find . -name ".txt" | grep "foo" | tr "\n" "\0" | xargs -0 rm
Esta vez tr
se utiliza para convertir todas las líneas nuevas en caracteres nulos.
"¿Por qué no puedo canalizar el resultado de búsqueda a rm?"
Cuando canaliza algo a un programa, la canalización reemplaza la entrada del teclado. Tenga esto en cuenta y hágase la siguiente pregunta:¿Qué haría rm
hacer con un teclado? ¿Eliminar tus pulsaciones de teclas? (un poco tonto de hecho) ¿Aceptar el control interactivo? (rm
no es interactivo excepto a veces cuando necesita confirmación, que de hecho puede ser proporcionada por una canalización.)
De hecho, cuando rm
ya se está ejecutando, no puede escribir comandos para permitir que elimine archivos... por lo que tampoco puede hacerlo con una canalización.
Si tiene en cuenta que una tubería reemplaza la combinación teclado/pantalla, las cosas parecerán inmediatamente más lógicas.
Ahora al revés. Puede canalizar un flujo de datos en grep
.¿Eso significa que puede permitir que grep lea las pulsaciones de teclas de su teclado como datos de entrada?
¡SÍ! Eso es en realidad lo que hace de forma nativa (sin canalización).
(por cierto, tenga en cuenta que no puede canalizar ni escribir el argumento de búsqueda en grep
)
Así que ahora sabes por qué no puedes tubería a rm y espera que funcione como un argumento de línea de comandos.
tl;dr:
Anatomía de un programa según la filosofía UNIX:
archivar, archivar, teclado, filtrar. -> Pipe solo reemplaza el teclado y la pantalla.
Pipe envía la salida del primer comando a la entrada estándar del segundo. rm
no acepta entrada estándar, por lo que no puede canalizarla. Podrías usar xargs
para lograr el mismo efecto. Puede encontrar un ejemplo para xargs
específicamente para su caso en la página man para xargs.