
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.sql
se pasa como dos argumentos a cat
. ¿Cuál es el enfoque habitual aquí?
Respuesta1
No es necesario ls
aquí. Es el shell que enumera el contenido del directorio expandiendo el *.sql
globo.
En un sistema GNU o FreeBSD:
printf '%s\0' *.sql | sort -nz | xargs -r0 cat --
(Usar \0
en lugar de \n
junto con -z/-0
garantiza que también funcione con nombres de archivos que contienen caracteres de nueva línea).
Tenga en cuenta que la clasificación numérica -n
asume que el número está al comienzo del nombre del archivo.
O si tienes zsh
:
cat ./*.sql(.n)
(El n
calificador 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.sql
agregué 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 --