Digamos que tengo un archivo llamado list_of_files.txt
donde cada línea corresponde a un archivo en el disco. Por ejemplo:
dir1/fileA.ext1
dir1/subdir1/fileB.ext2
fileC.ext3
dir2/fileD.ext4
fileE.ext5
Quiero seleccionar aleatoriamente una cantidad de archivos de esa lista y cksum
calcularlos md5sum
.
Sé que puedo seleccionar aleatoriamente, digamos, 3 archivos con shuf -n 3 list_of_files.txt
, pero ¿cómo puedo cksum
tratarlos como nombres de archivos en lugar de contenido de texto?
Respuesta1
Si las rutas del archivo terminan en una nueva línea y se proporcionan tal como están, es decir, si cada línea es una ruta literal separada, entonces un bucle de shell funcionará:
shuf -n 3 list_of_files.txt | while IFS= read -r pth; do
cksum "$pth"
done
También hay xargs
(ver elespecificación POSIXy más avanzadoÑUxargs
), hayÑUparallel
(notaparallel
existe no-GNUy no me refiero a eso). Con la herramienta adecuada y las opciones adecuadas, puede hacer que un cksum
proceso tenga más de una ruta ( cksum
en general, generar menos procesos es beneficioso) o ejecutar dos o más cksum
procesos en paralelo.
Para procesar tan solo tres archivos, puedo ceñirme a nuestro bucle de shell debido a la portabilidad; a menos que los archivos sean grandes y espero que tres cksum
procesos que se ejecutan en paralelo sean sustancialmente más rápidos que uno cksum
a la vez. No soy un experto en GNU parallel
, pero parece que la solución es tan simple como:
shuf -n 3 list_of_files.txt | parallel cksum
De forma predeterminada, GNU parallel
limita la cantidad de trabajos simultáneos según la cantidad de núcleos de CPU. Hoy en día son comunes tres o más núcleos, por lo que el comando probablemente ejecutará tres cksum
procesos en paralelo. Sin embargo, formalmente esto no es portátil. También tenga en cuenta que procesar tres archivos en paralelo significa leer tres archivos en paralelo. La E/S puede ser un cuello de botella y esto puede reducir el beneficio de los trabajos paralelos o incluso empeorar las cosas.
Incluso entonces parallel
puede resultar útil. Utilícelo -j 1
para limitar el número de trabajos a 1:
shuf -n 3 list_of_files.txt | parallel -j 1 cksum
Los archivos se procesarán secuencialmente como en nuestro bucle de shell, pero la sintaxis es más simple. En el caso de nuestro bucle Shell, necesita saber que deseaIFS= read -r pth
, No solo read pth
; y necesitas saber que (en muchos aspectos) quierescksum "$pth"
, no cksum $pth
. La solución con GNU parallel
es menos propensa a errores.BESO.
De forma predeterminada, Note xargs
interpreta las comillas y las barras invertidas y considera los espacios como delimitadores. Probablemente este medio shuf -n 3 list_of_files.txt | xargs cksum
no sea lo que desea. Su ejemplo funcionará, pero en general necesita comillas y/o barras invertidas adicionales en el archivo; xor necesitas xargs -d '\n'
dónde -d
hay una opción no portátil de GNU xargs
. Mi suposición era que "las rutas del archivo terminan en una nueva línea y se proporcionan tal cual". Con esta suposición, GNU parallel
funciona de inmediato (es decir, sin opciones adicionales), xargs no. Con GNU xargs
puedes hacer esto:
shuf -n 3 list_of_files.txt | xargs -d '\n' cksum
Si puedes usar GNU xargs
(para salvar el día -d '\n'
), entonces probablemente puedas usar GNU parallel
. Si lo olvida -j 1
al usar GNU parallel
, el comando puede funcionar peor pero seguirá funcionando. Si olvida -d '\n'
cuando usa GNU xargs
y los nombres de ruta se proporcionan tal como están, entonces es un error. Por eso recomendé GNU parallel
primero.
GNU paralelo es capaz de procesar cadenas terminadas en nulo (la opción es -0
), al igual que GNU xargs
( -0
en lugar de -d '\n'
) y GNU shuf
(con -z
). Su archivo de entrada utiliza líneas terminadas en nueva línea, pero si alguna vez necesita trabajar con nombres de ruta que (pueden) contener caracteres de nueva línea, entonces cambiar el terminador en el archivo y agregar las opciones adecuadas es el camino a seguir.