Este enfoque a menudo me gusta usar.
ls | sed "s|^\(.*\)\.\([^\.]*\)$|mv \1.\2 \\`echo \1 \| md5sum \| cut -d' ' -f 1\\`.\2|" | sh -
El comando "ls" produce una secuencia de líneas de texto. El comando "sed" transforma cada línea con reglas de coincidencia de patrones. El comando "sed" genera un comando "mv" que luego se canaliza a través de un shell "sh" para su ejecución. Los parámetros del comando "mv" son como "mv oldfilename newfilename", que cambia el nombre del archivo. Construyo el nuevo nombre de archivo con un comando sed que toma la parte anterior al último punto, y lo hace eco en la entrada del comando "md5sum", y luego toma solo el hash de su salida.
Recorriendo mi proceso, primero enumere los archivos ('head -n 3' para ver las primeras 3 líneas):
ls | head -n 3
1000-26092016.xml
1000-27092016.xml
12312-28092016.xml
Luego piense en la transformación con sed (aún no canaliza ningún comando generado a través de un shell)
ls | sed "s|^\(.*\)\.\([^\.]*\)$|mv \1.\2 \1.\2|" | head -n 3
mv 1000-26092016.xml 1000-26092016.xml
mv 1000-27092016.xml 1000-27092016.xml
mv 12312-28092016.xml 12312-28092016.xml
Hay tres patrones de coincidencia:
^\(.*\) = match from start-of-line up to a dot
\. = matches a single dot
\([^\.]*\)$ = match 0-or-more non-dot chars from end of line
Quiero usar sed para reemplazar un nombre de archivo de entrada con "mv filename NEWfilename", pero como estoy canalizando comandos a través de un shell, puedo generar comandos que obtienen el md5sum, como este
echo "1000-26092016" | md5sum
55b18a6b0add4a318b0079e18512b4e8 -
para obtener solo el hash
echo "1000-26092016" | md5sum | cut -d' ' -f 1
55b18a6b0add4a318b0079e18512b4e8
En un shell de Unix, podemos usar operadores de backtick (`some_command`) para ejecutar un subcomando, por ejemplo
echo "howdy date there"
howdy date there
echo "howdy `date` there"
howdy Fri Sep 15 18:39:00 IST 2017 there
Volviendo al comando mv, quiero que sed produzca "mv here there" con "there" reemplazado por un comando backtick para obtener el md5sum. La cadena dentro de la cadena de reemplazo de sed comienza así
ls | sed "s|^\(.*\)\.\([^\.]*\)$|mv \1.\2 `echo \1 | md5sum | cut -d' ' -f 1`.\2|" | head -n 3
mv 1000-26092016.xml b026324c6904b2a9cb4b88d6d61c81d1.xml
mv 1000-27092016.xml b026324c6904b2a9cb4b88d6d61c81d1.xml
mv 12312-28092016.xml b026324c6904b2a9cb4b88d6d61c81d1.xml
Pero claramente está haciendo el mismo hash para cada nombre de archivo, ya que el comando backticked-command se ejecuta antes de que sed vea la cadena. Para detener el shell que ejecuta el comando backtick para que sed genere los backticks, tenemos que anteponer barras diagonales (también al carácter de tubería), así que nuevamente:
ls | sed "s|^\(.*\)\.\([^\.]*\)$|mv \1.\2 \`echo \1 \| md5sum \| cut -d' ' -f 1\`.\2|" | head -n 3
mv 1000-26092016.xml `echo 1000-26092016 | md5sum | cut -d' ' -f 1`.xml
mv 1000-27092016.xml `echo 1000-27092016 | md5sum | cut -d' ' -f 1`.xml
mv 12312-28092016.xml `echo 12312-28092016 | md5sum | cut -d' ' -f 1`.xml
La salida también necesita nombres de archivo para ser citados en caso de espacios, por lo que
ls | sed "s|^\(.*\)\.\([^\.]*\)$|mv \"\1.\2\" \"\`echo \1 \| md5sum \| cut -d' ' -f 1\`.\2\"|" | grep trick
mv "a trick€€ fíle nÁme.xml" "`echo a trick€€ fíle nÁme | md5sum | cut -d' ' -f 1`.xml"
Así que vamos a probar este, pasándolo a través de un shell:
ls | sed "s|^\(.*\)\.\([^\.]*\)$|mv \"\1.\2\" \"\`echo \1 \| md5sum \| cut -d' ' -f 1\`.\2\"|" | grep trick | sh -
Funcionó ? supongo:
echo "a trick€€ fíle nÁme" | md5sum
629db9c3071928ba0746f18444713b65 -
ls 629db9c3071928ba0746f18444713b65*
629db9c3071928ba0746f18444713b65.xml
Aquí hay un enfoque para la verificación cruzada; use la opción "ls" "-i" para generar el sistema de archivos unix i-node (que no cambia con "mv"):
ls -1i | sort -n > .before
ls | sed "s|^\(.*\)\.\([^\.]*\)$|mv \"\1.\2\" \"\`echo \1 \| md5sum \| cut -d' ' -f 1\`.\2\"|" | sh -
ls -1i | sort -n > .after
cut -d' ' -f 1 .before | while read I ; do echo "mv'd \"`grep ${I} .before`\" to \"`grep ${I} .after`\"" | sed "s| *$I *||g" ; done | head -n 3
mv'd "1000-26092016.xml" to "55b18a6b0add4a318b0079e18512b4e8.xml"
mv'd "1000-27092016.xml" to "b1baa80d99d5edf85c8aeb98185dd440.xml"
mv'd "12312-28092016.xml" to "2b2d692bd047b64c99f7b9161349d430.xml"
O, usando el comando "pegar" (paquete 'coreutils')
paste .before .after | head -n 3
36703389 1000-26092016.xml 36703389 55b18a6b0add4a318b0079e18512b4e8.xml
36703390 1000-27092016.xml 36703390 b1baa80d99d5edf85c8aeb98185dd440.xml
36703391 12312-28092016.xml 36703391 2b2d692bd047b64c99f7b9161349d430.xml