¿Por qué esto no funciona? "Ls * .txt | xargs cat> all.txt ”(todos los archivos en un solo documento txt)

20

¿Por qué esto no funciona?

ls *.txt | xargs cat > all.txt

(Quiero unir el contenido de todos los archivos de texto en un solo archivo 'all.txt'). Encontrar con -exec también debería funcionar, pero realmente me gustaría entender la sintaxis de xargs.

Gracias

ajo
fuente
1
Aunque no lo uses lspara esto . Si realmente no puede usar cat *.txt >all.txt, intente printf '%s\0' *.txt | xargs -r0 cat >ally luego mv all all.txtevite que el archivo haga referencia a sí mismo.
tripleee

Respuestas:

27

ls *.txt | xargs cat >> all.txt

podría funcionar un poco mejor, ya que se agregaría a all.txt en lugar de crearlo nuevamente después de cada archivo.

Por cierto, cat *.txt >all.txttambién funcionaría. :-)

Janne Pikkarainen
fuente
66
El gato * .txt> all.txt es naturalmente mejor. Gracias
ajo
1
Sin embargo, el ... | xargs cat >> all.txt o> all.txt siempre devuelve un error con xargs: comilla simple sin igual ... ¿Es porque xargs toma todo lo que sigue como comando?
ajo
1
¿Tienes nombres de archivo con espacios? Si es así, utilice algo como "find / your / path -iname '* .txt' -print0 | xargs -0 cat >> all.txt" en su lugar
Janne Pikkarainen
1
no, reemplacé todos los espacios de nombre de archivo con . Pero pensando en ello, es probable que algunos nombres de archivo incluyan comillas simples como en listing_O'Connor .txt, ¡este podría ser el problema!
ajo
Sí, ese es el problema entonces. :) La forma más fácil y más segura es usar find con -print0 combinado con xargs -0, entonces toda la cadena usará el carácter NULL como separador y los espacios en blanco y los caracteres especiales se ocuparán automáticamente.
Janne Pikkarainen
3

Si algunos de sus nombres de archivo contienen ', "o el espacio xargsfallará debido al problema del separador

En general, nunca corras xargssin -0, ya que volverá y te morderá algún día.

Considere usar GNU Parallel en su lugar:

ls *.txt | parallel cat > tmp/all.txt

o si lo prefieres:

ls *.txt | parallel cat >> tmp/all.txt

Obtenga más información sobre GNU Parallel http://www.youtube.com/watch?v=OpaiGYxkSuQ

Ole Tange
fuente
1

all.txt es un archivo en el mismo directorio, por lo que cat se confunde cuando quiere escribir desde el mismo archivo en el mismo archivo.

Por otra parte:

ls *.txt | xargs cat > tmp/all.txt

Esto se leerá de los archivos de texto en su directorio actual en all.txt en un subdirectorio (no incluido con *.txt).

Jeremy Smyth
fuente
Sigue siendo el siguiente error: xargs: comilla simple sin igual; por defecto, las cotizaciones son especiales para xargs a menos que use la opción -0
ajo
1
¿Tiene un archivo .txt con una sola comilla en su nombre?
Jeremy Smyth
0

También puede encontrar una limitación de longitud de línea de comando. Parte del motivo de uso xargses que divide la entrada en fragmentos seguros del tamaño de una línea de comandos. Entonces, imagine una situación en la que tiene cientos de miles de archivos .txt en el directorio. ls *.txtfallará. Necesitarías hacer

ls | grep .txt$ |xargs cat > /some/other/path/all.txt

.txt$en este caso es una expresión regular que coincide con todo lo que termina en .txt (por lo que no es exactamente igual *.txt, ya que si tiene un archivo llamado atxt, entonces *.txtno coincidiría, pero la expresión regular sí lo haría).

El uso de otra ruta se debe a que, como han señalado otras respuestas, all.txt coincide con el patrón, *.txtpor lo que habría un conflicto entre la entrada y la salida.

Tenga en cuenta que si tiene algún archivo con 'su nombre (y esta puede ser la causa del unmatched single quoteerror), querrá hacer

ls | grep --null .txt$ | xargs -0 cat > /some/other/path/all.txt

La opción --null le dice a grep que use la salida separada por un carácter \0(también conocido como nulo) en lugar de la nueva línea predeterminada, y la -0opción `xargs le dice que espere su entrada en el mismo formato. Esto funcionaría incluso si tuviera nombres de archivo con nuevas líneas en ellos.

Brian Minton
fuente