
Quiero usar buscar para buscar ciertos archivos y luego usar xargs con cp y sed para mover estos archivos a otra carpeta y cambiarles el nombre. Sé cómo hacer esto en bucle, pero eso no es lo que estoy buscando.
Lo intenté:
find ${FOLDER} -iname "*${SOME_STRING}*" | xargs -I {} cp {} $(echo {} | sed 's/ABC/XYZ/g')
¿Por qué esto no funciona y cuál sería una solución?
Respuesta1
Prueba esto. No necesita xargs
, solo find
y . No cambiará ningún archivo, perosed
copy
voluntadimprima una lista de comandos de shell para copiar los archivos. Entonces, si le gustan los comandos que imprime, ejecútelo nuevamente y elimine el #
antes sh -x
de la última línea y deje que el shell ejecute los comandos.
find "${FOLDER:-.}" -iname "*${SOME_STRING:-ABC}*" |
sed "
s/^/'/ # surround filename with single quotes
s/$/'/
h # save filename in the sed hold space
s/ABC/XYZ/g # change filename
H # append to hold space (separates with newline)
g # get original and modified from hold
s/\n/ /g # replace the newline with a space
s/^/cp -i/ # make it into a copy command
" #| sh -x # optionally pipe to shell
¿Por qué este enfoque es mejor que xargs
en este caso? Porque este método inicia solo 3 procesos en total ( find
, sed
y sh
) además del cp
comando requerido para cada archivo.
Para usar xargs
, procesar cada nombre de archivo requeriría más procesos que el único cp
comando requerido.
Es mucho más eficiente dejar que se genere la invocación de sedtodode los cp
comandos, que invocar un nuevo sed
proceso para cada nombre de archivo.
Respuesta2
Usando GNU Parallel se ve así:
find ${FOLDER} -iname "*${SOME_STRING}*" |
parallel cp {} '{= s/ABC/XYZ/g =}'
La construcción {= =} contiene una expresión Perl que cambia $_.
Una de las ventajas es que GNU Parallel hace lo correcto incluso si tiene archivos llamados:
My brother's 12" records worth >100$.txt
o horrores como:
touch Y-"$(perl -e 'print pack("c*",1..9,11..46,48..255)')"