
En un directorio tengo una cierta cantidad de archivos. Podrían ser 53 archivos txt, pero también podría tener 123 archivos. Los archivos tienen varios nombres aleatorios, pero todos tienen el identificador de archivo..txt
Puedo obtener una lista de todos los archivos con ls y ponerla en una variable.
list_of_txt_files=$(ls *.txt)
Pero me gustaría dividir la lista en varias listas individuales, cada lista con sólo 10 elementos, es decir, una carpeta con 53 archivos txt, debería darme 6 listas. Es decir, 5 listas con 10 nombres de archivos y una sexta lista con 3 nombres de archivos, y mi ejemplo con 123 archivos txt en un directorio debería darme 12 listas con 10 nombres de archivos y una decimotercera lista con solo 3 nombres de archivos. .
Con mi ejemplo con 53 archivos txt: lista no. 1 mantendría el primer archivo hasta el décimo archivo y listaría no. 2 mantendría desde el undécimo archivo hasta el vigésimo, y así sucesivamente. Titulé mi pregunta del iésimo al jésimo elemento de una lista, ya que supongo que otras personas podrían querer dividir la lista de manera diferente. Quizás desde el primer archivo hasta el archivo número 100 en un directorio.
El objetivo final es poder usar estas listas en un bucle for do y usar el comando cat para escribir el contenido de diez archivos por lista en un archivo por conjunto de diez archivos; es decir, en mi ejemplo con 53 archivos en un directorio, esto me daría 6 archivos. Donde los primeros 5 archivos contienen el contenido de los 50 archivos txt originales y el sexto archivo contiene el contenido de los últimos 3 archivos txt restantes.
He considerado usar el comando head o tail, pero no puedo entender cómo especificar rangos para estos dos comandos.
Respuesta1
En un caparazón conmatrices, usalos, usalos a ellos. Decir con Bash:
$ touch {01..53}
$ files=(*)
$ echo "${files[@]:0:10}"
01 02 03 04 05 06 07 08 09 10
$ for ((i = 0 ; i < ${#files[@]} ; i += 10 )) ; do
echo "${files[@]:i:10}" ;
# or
# cat "${files[@]:i:10}" > set-$(( i / 10 ))
done
01 02 03 04 05 06 07 08 09 10
11 12 13 14 15 16 17 18 19 20
21 22 23 24 25 26 27 28 29 30
31 32 33 34 35 36 37 38 39 40
41 42 43 44 45 46 47 48 49 50
51 52 53
Elexpansión de subcadena(segmento de matriz) "${files[@]:i:10}"
se expande a una lista de palabras, no a una sola cadena, por lo que puede recorrerla en bucle:
for f in "${files[@]:i:10}" ; do
somecmd "$f"
done
Nodo files=$(ls *.txt)
, ls
es completamente redundante allí, es el shell el que evalúa el comodín de todos modos. Por lo general, simplemente guarda el patrón comodín en una variable ( pat=*.txt
) y lo usa (sin comillas) cuando sea necesario, o si desea expandirlo a los nombres de archivos reales, úselo echo *.txt
en lugar de ls
. Para manejar listas de nombres de archivos, las matrices son mejores, si no está limitado a un shell POSIX simple.
En cuanto a dividir una lista con head
y tail
, necesitaría hacer algo como | head -20 | tail -10
obtener las líneas 11 a 20. O usar sed: | sed -n 11,20p
.
Respuesta2
Con cualquier shell tipo Bourne (excepto el shell Bourne que no podía acceder a elementos posicionales $9
), puedes hacer:
set -- *.txt
while [ "$#" -gt 0 ]; do
something with "$1" ${2+"$2"} ${3+"$3"}... ${10+"${10}"}
[ "$#" -gt 10 ] || break
shift 10
done
Con GNU xargs
y shells con soporte para sustitución de procesos:
xargs -n10 -r0a <(printf '%s\0' *.txt) something with
Con zsh
:
files=(*.txt(N))
while (($#files)) {
something with $files[1,10]
files[1,10]=()
}
O:
autoload -U zargs
xargs -l10 -- *.txt -- something with
También tenga en cuenta que puede utilizar un rango en zsh
los globos:
something with *.txt([1,10])