¿Cómo orderar los nombres de files con espacios en ellos y concatenar los files?

Tengo la mala suerte de lidiar con nombres de files que contienen espacios. Quiero concatenar files cuyos nombres de file contengan espacios. También quiero orderar los nombres de file numéricamente. Obviamente, el siguiente falla:

cat $(ls *.sql | sort -n) 

ya que foo bar.sql se pasa como dos arguments a cat . ¿Cuál es el enfoque habitual aquí?

No hay necesidad de ls aquí. Es el shell que enumera el contenido del directory al expandir el glob *.sql .

En un sistema GNU o FreeBSD:

 printf '%s\0' *.sql | sort -nz | xargs -r0 cat -- 

(usar \0 lugar de \n junto con -z/-0 asegura que también funcione con nombres de file que contengan caracteres de nueva línea).

Tenga en count que la sorting numérica con -n supone que el número está al comienzo del nombre de file.

O si tienes zsh :

 cat ./*.sql(.n) 

(El calificador n glob es para permitir la sorting numérica (también funciona cuando el número no está al principio, siempre que todos los nombres de los files tengan el mismo prefijo (como file12.sql , file2.sql ). file2.sql . file12.sql , solo file2.sql files regulares Agregue D si también desea files ocultos como .foo.sql ).

Utilice xargs (suponiendo la implementación de GNU) con un delimitador personalizado (suponiendo que los nombres de file no contengan líneas nuevas):

 ls -1d -- *.sql | sort -n | xargs -d "\n" cat -- 

Puedes hacer cat $(ls -1) si anulas IFS. IFS es la variable de shell que le dice a BASH qué caracteres usar como delimitador. El valor pnetworkingeterminado para IFS es espacio, pestaña, nueva línea. Si cambia IFS a solo nueva línea, entonces puede hacer cat $(ls -1) .

No hay nada de malo con las otras respuestas, pero esta podría ser una respuesta más directa a cómo tratar los espacios en general y esta respuesta introduce la variable IFS con la que la mayoría no está familiarizada.

 #!/bin/bash dir=$(mktemp -d) for x in $(seq 10); do echo $x > "$dir/$(date) $x.txt" done pushd $dir ls -1 $dir # Set IFS to newline only inorder to deal with the spaces in the file names # oldIFS=$IFS IFS=$'\n' cat $(ls -1 $dir) IFS=$oldIFS 

Salida

 [sri@localhost test]$ ./test /tmp/tmp.IuXCBzbTLj ~/test Mon Nov 17 06:38:52 EST 2014 10.txt Mon Nov 17 06:38:52 EST 2014 1.txt Mon Nov 17 06:38:52 EST 2014 2.txt Mon Nov 17 06:38:52 EST 2014 3.txt Mon Nov 17 06:38:52 EST 2014 4.txt Mon Nov 17 06:38:52 EST 2014 5.txt Mon Nov 17 06:38:52 EST 2014 6.txt Mon Nov 17 06:38:52 EST 2014 7.txt Mon Nov 17 06:38:52 EST 2014 8.txt Mon Nov 17 06:38:52 EST 2014 9.txt 10 1 2 3 4 5 6 7 8 9 

Aquí hay un enlace a cierta documentation sobre IFS. http://bash.cyberciti.biz/guide/ $ IFS. Creo que lo supe hace mucho time leyendo el libro BASH de O'Rielly.