¿Cómo se ejecuta un comando para cada línea de un archivo?

Por ejemplo, ahora estoy usando lo siguiente para cambiar un par de archivos cuyas rutas de acceso de Unix escribí a un archivo:

cat file.txt | while read in; do chmod 755 "$in"; done 

¿Hay una manera más elegante y segura?

Si su archivo no es demasiado grande y todos los archivos están bien nombrados (sin espacios u otros caracteres especiales como comillas), simplemente puede:

 chmod 755 $( 

Si tiene caracteres especiales y / o muchas líneas en file.txt .

 xargs -0 chmod 755 < <(tr \\n \\0  

si su comando necesita ejecutarse exactamente 1 vez por entrada:

 xargs -0 -n 1 chmod 755 < <(tr \\n \\0  

Esto no es necesario para esta muestra, ya que chmod acepta múltiples archivos como argumento, pero esto coincide con el título de la pregunta.

Para algunos casos especiales, incluso podría definir la ubicación del argumento del archivo en comandos generados por xargs :

 xargs -0 -I '{}' -n 1 myWrapper -arg1 -file='{}' wrapCmd < <(tr \\n \\0  

Sí.

 while read in; do chmod 755 "$in"; done < file.txt 

De esta forma puedes evitar un proceso de cat .

cat casi siempre es malo para un propósito como este. Puede leer más sobre el uso inútil del gato.

Si sabe que no tiene espacios en blanco en la entrada:

 xargs chmod 755 < file.txt 

Si puede haber espacios en blanco en las rutas, y si tiene xargs de GNU:

 tr '\n' '\0' < file.txt | xargs -0 chmod 755 

si tiene un buen selector (por ejemplo, todos los archivos .txt en un directorio), podría hacer lo siguiente:

 for i in *.txt; do chmod 755 "$i"; done 

Bash para el bucle

o una variante tuya:

 while read line; do chmod 755 "$line"; done  

Si desea ejecutar su comando en paralelo para cada línea, puede usar GNU Parallel

 parallel -a   

Cada línea de su archivo se pasará al progtwig como argumento. De forma predeterminada, el parallel ejecuta la mayor cantidad de subprocesos que cuenten sus CPU. Pero puedes especificarlo con -j

Veo que etiquetó a bash, pero Perl también sería una buena manera de hacer esto:

 perl -p -e '`chmod 755 $_`' file.txt 

También puede aplicar una expresión regular para asegurarse de obtener los archivos correctos, por ejemplo, para procesar solo archivos .txt:

 perl -p -e 'if(/\.txt$/) `chmod 755 $_`' file.txt 

Para “previsualizar” lo que está sucediendo, simplemente reemplace los trazos con comillas dobles y anteponga a la print :

 perl -p -e 'if(/\.txt$/) print "chmod 755 $_"' file.txt 

También puede usar AWK que le puede dar más flexibilidad para manejar el archivo

 awk '{ print "chmod 755 "$0"" | "/bin/sh"}' file.txt 

si su archivo tiene un separador de campo como:

campo1, campo2, campo3

Para obtener solo el primer campo que haces

 awk -F, '{ print "chmod 755 "$1"" | "/bin/sh"}' file.txt 

Puede consultar más detalles sobre la documentación de GNU https://www.gnu.org/software/gawk/manual/html_node/Very-Simple.html#Very-Simple