¿Cómo ordenar nombres de archivos con espacios y concatenar los archivos?

¿Cómo ordenar nombres de archivos con espacios y concatenar los archivos?

Tengo la desgracia de lidiar con nombres de archivos que contienen espacios. Quiero concatenar archivos cuyos nombres contengan espacios. También quiero ordenar los nombres de archivos numéricamente. Obviamente falla lo siguiente:

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

since foo bar.sqlse pasa como dos argumentos a cat. ¿Cuál es el enfoque habitual aquí?

Respuesta1

No es necesario lsaquí. Es el shell que enumera el contenido del directorio expandiendo el *.sqlglobo.

En un sistema GNU o FreeBSD:

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

(Usar \0en lugar de \njunto con -z/-0garantiza que también funcione con nombres de archivos que contienen caracteres de nueva línea).

Tenga en cuenta que la clasificación numérica -nasume que el número está al comienzo del nombre del archivo.

O si tienes zsh:

cat ./*.sql(.n)

(El ncalificador global es para habilitar la clasificación numérica (también funciona cuando el número no está al principio, siempre que todos los nombres de archivos tengan el mismo prefijo (como file12.sql, ). También file2.sqlagregué para incluir solo archivos normales. Agregue si también desea archivos ocultos como )..D.foo.sql

Respuesta2

Puede hacerlo cat $(ls -1)si anula IFS. IFS es la variable de shell que le dice a BASH qué caracteres usar como delimitador. El valor predeterminado para IFS es espacio, tabulación y nueva línea. Si cambia IFS a solo nueva línea, puede hacerlo cat $(ls -1).

No hay nada de malo en las otras respuestas, pero esta podría ser una respuesta más directa sobre 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

Producción

[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 alguna documentación sobre IFS. http://bash.cyberciti.biz/guide/$IFS. Creo que lo aprendí hace mucho tiempo leyendo el libro BASH de O'Rielly.

Respuesta3

Úselo xargs(asumiendo la implementación GNU) con un delimitador personalizado (asumiendo que los nombres de archivos no contienen nuevas líneas):

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

información relacionada