lote renomear arquivos zip com base em nomes de arquivos contidos

2

Eu tenho um diretório com 15000 arquivos zip. Gostaria de renomear todos os arquivos que, quando descompactados, contêm um arquivo no formato

YYYYMMDD_IPC.csv

onde YYYYMMDD é uma data, mas para os propósitos deste problema é qualquer string de exatamente 8 dígitos. Então, o próprio arquivo zip deve ser renomeado para

YYYYMMDD_IPC.zip.

Cheguei até a seguinte linha de comando, mas não sei como capturar o YYYYMMDD do arquivo contido para usar a fim de renomear os arquivos zip:

find . -iname '*.zip' | while read file; do unzip -l "$file" | grep -q -P '\d{8}_IPC.csv' && echo $file; done 2>&- 

Obrigado pela leitura.

    
por user2926302 25.09.2015 / 01:17

1 resposta

4
find . -iname '*.zip' -exec bash -c 'name=$(unzip -qql ""  '*_IPC.csv' | grep -oE '[[:digit:]]{8}_IPC.csv' | head -n1); [ "$name" ] && mv "" "${name%csv}zip"' none {} ';'

Como funciona

Este comando tem o formato:

find . -iname '*.zip' -exec bash -c '...' none {} ';'

Isso procura o arquivo .zip no diretório atual e todos os subdiretórios abaixo dele. Para cada arquivo encontrado, o comando bash entre aspas simples é executado. O nome do arquivo encontrado é fornecido no argumento um, , para o comando bash. No nosso caso, o comando bash tem duas partes. O primeiro extrai o nome do arquivo csv e o salva na variável bash name :

name=$(unzip -qql ""  '*_IPC.csv' | grep -oE '[[:digit:]]{8}_IPC.csv' | head -n1)

O acima usa substituição de comando : o comando dentro de $(...) é executado e sua saída padrão é capturada. Neste caso, atribuímos a variável name . O comando unzip -qql "" '*_IPC.csv' extrai silenciosamente todos os nomes de arquivo do arquivo zip que correspondem ao glob *_IPC.csv . Nós não precisamos limitar ao glob *_IPC.csv , mas, se o arquivo zip tiver muitos arquivos, isso pode acelerar as coisas.

O comando grep, rep -oE '[[:digit:]]{8}_IPC.csv' seleciona apenas os nomes que começam com 8 dígitos. O comando head -n1 seleciona o primeiro nome encontrado. Se houvesse apenas um desses nomes, head -n1 não seria necessário. Mas, manter head poderia acelerar as coisas, porque faz com que o pipeline termine após a primeira partida.

A segunda parte testa que obtivemos um name não vazio e, em caso afirmativo, renomeia o arquivo zip:

[ "$name" ] && mv "" "${name%csv}zip"

O texto acima usa remoção de sufixo para alterar o nome do arquivo csv para um nome de arquivo zip. ${name%csv} retorna $name depois de ter removido o sufixo csv . ${name%csv}zip adiciona um sufixo de zip.

    
por John1024 25.09.2015 / 01:32