Isso na abordagem eu geralmente gosto de usar.
ls | sed "s|^\(.*\)\.\([^\.]*\)$|mv . \'echo \| md5sum \| cut -d' ' -f 1\'.|" | sh -
O comando "ls" produz um fluxo de linhas de texto.
O comando "sed" transforma cada linha com regras de correspondência de padrões.
O comando "sed" gera um comando "mv", que é então canalizado através de um shell "sh" para execução.
Os parâmetros do comando "mv" são como "mv oldfilename newfilename", que renomeia o arquivo.
Eu construo o novo nome de arquivo com um comando sed que toma a parte antes do último ponto, e o ecoa na entrada do comando "md5sum", e então pega apenas o hash da sua saída.
Andando pelo meu processo, primeiro liste os arquivos ('head -n 3' para ver apenas as 3 primeiras linhas):
ls | head -n 3
1000-26092016.xml
1000-27092016.xml
12312-28092016.xml
Em seguida, pense em transformar com sed (ainda não canalizar nenhum comando gerado por meio de um shell)
ls | sed "s|^\(.*\)\.\([^\.]*\)$|mv . .|" | head -n 3
mv 1000-26092016.xml 1000-26092016.xml
mv 1000-27092016.xml 1000-27092016.xml
mv 12312-28092016.xml 12312-28092016.xml
Existem três padrões de correspondência:
^\(.*\) = match from start-of-line up to a dot
\. = matches a single dot
\([^\.]*\)$ = match 0-or-more non-dot chars from end of line
Eu quero usar sed para substituir um nome de arquivo de entrada por "mv filename NEWfilename",
mas como eu estou piping comandos através de um shell, eu posso gerar comandos que obtêm o md5sum, como este
echo "1000-26092016" | md5sum
55b18a6b0add4a318b0079e18512b4e8 -
para obter apenas o hash
echo "1000-26092016" | md5sum | cut -d' ' -f 1
55b18a6b0add4a318b0079e18512b4e8
Em um shell unix, podemos usar operadores backtick ('some_command') para executar um subcomando, portanto, por exemplo
echo "howdy date there"
howdy date there
echo "howdy 'date' there"
howdy Fri Sep 15 18:39:00 IST 2017 there
De volta ao comando mv, quero que o sed produza "mv here there" com "there" substituído por um comando backtick para obter o md5sum.
A string dentro do sed replace-string começa assim
ls | sed "s|^\(.*\)\.\([^\.]*\)$|mv . 'echo | md5sum | cut -d' ' -f 1'.|" | head -n 3
mv 1000-26092016.xml b026324c6904b2a9cb4b88d6d61c81d1.xml
mv 1000-27092016.xml b026324c6904b2a9cb4b88d6d61c81d1.xml
mv 12312-28092016.xml b026324c6904b2a9cb4b88d6d61c81d1.xml
Mas está claramente fazendo o mesmo hash para cada nome de arquivo, já que o comando backticked está sendo executado antes que o sed veja a string.
Para parar o shell executando o comando backtick, então sed irá mostrar os backticks, nós temos que preceder barras (também para o pipe-character), então novamente:
ls | sed "s|^\(.*\)\.\([^\.]*\)$|mv . \'echo \| md5sum \| cut -d' ' -f 1\'.|" | 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
A saída também precisa de nomes de arquivos para serem citados no caso de espaços, então
ls | sed "s|^\(.*\)\.\([^\.]*\)$|mv \".\" \"\'echo \| md5sum \| cut -d' ' -f 1\'.\"|" | grep trick
mv "a trick€€ fíle nÁme.xml" "'echo a trick€€ fíle nÁme | md5sum | cut -d' ' -f 1'.xml"
Então, vamos experimentar este, canalizando-o através de um shell:
ls | sed "s|^\(.*\)\.\([^\.]*\)$|mv \".\" \"\'echo \| md5sum \| cut -d' ' -f 1\'.\"|" | grep trick | sh -
Funcionou? eu acho:
echo "a trick€€ fíle nÁme" | md5sum
629db9c3071928ba0746f18444713b65 -
ls 629db9c3071928ba0746f18444713b65*
629db9c3071928ba0746f18444713b65.xml
Aqui está uma abordagem para verificação cruzada; use a opção "ls" "-i" para produzir o i-node do sistema de arquivos unix (que não muda com "mv"):
ls -1i | sort -n > .before
ls | sed "s|^\(.*\)\.\([^\.]*\)$|mv \".\" \"\'echo \| md5sum \| cut -d' ' -f 1\'.\"|" | 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"
Ou, usando o comando "colar" (pacote '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