Como renomear arquivos em massa para nomes de arquivo numéricos no Linux

Shutterstock / estherpoon
Deseja renomear um conjunto completo de arquivos para uma sequência numérica (1. pdf, 2. pdf, 3. pdf, …) no Linux? Isso pode ser feito com alguns scripts leves e este artigo mostrará como fazer exatamente isso.
Nomes de arquivos numéricos
Normalmente, quando digitalizamos um arquivo PDF usando algum hardware (telefone celular, scanner de PDF dedicado), o nome do arquivo será algo como 2020_11_28_13_43_00. pdf. Muitos outros sistemas semiautomáticos produzem nomes de arquivos com base em data e hora semelhantes.
Às vezes, o arquivo também pode conter o nome do aplicativo que está sendo usado ou alguma outra informação como, por exemplo, o DPI aplicável (pontos por polegada) ou o tamanho do papel digitalizado.
Ao coletar arquivos PDF de fontes diferentes, as convenções de nomenclatura de arquivo podem diferir significativamente e pode ser bom padronizar em um nome de arquivo numérico (ou parcialmente numérico).
Isso também se aplica a outros domínios e conjuntos de arquivos. Por exemplo, suas receitas ou coleta de fotos, amostras de dados geradas por sistemas de monitoramento automatizados, arquivos de log prontos para arquivamento, um conjunto de arquivos SQL para o engenheiro de banco de dados e, geralmente, quaisquer dados coletados de diferentes fontes com diferentes esquemas de nomenclatura.
Renomear arquivos em massa para nomes de arquivos numéricos
No Linux, é fácil renomear rapidamente um conjunto completo de arquivos com nomes de arquivo completamente diferentes, para uma sequência numérica. “ Fácil ” significa “ fácil de executar ” aqui: o problema de renomear arquivos em massa para números numéricos é complexo para codificar em si: o script oneliner abaixo levou de 3 a 4 horas para pesquisar, criar e testar. Muitos outros comandos tentados todos tinham limitações que eu queria evitar.
Observe que nenhuma garantia é dada ou fornecida e este código é fornecido & # 8216; no estado em que se encontra ’. Por favor, faça sua própria pesquisa antes de executá-lo. Dito isso, eu o testei com sucesso em arquivos com vários caracteres especiais e também em mais de 50 mil arquivos sem que nenhum arquivo fosse perdido. Eu também verifiquei um arquivo chamado 'a' $ '\ n''a. pdf' que contém uma nova linha.
se [! -r _e -a! -r _c]; em seguida, echo 'pdf' > _e; echo 1 > _c; encontrar. -name "*. $ (cat _e)" -print0 | xargs -0 -I {} bash -c 'mv -n "{}" $ (cat _c). $ (cat _e); echo $ [$ (cat _c) + 1] > _c '; rm -f _e _c; fi
Vamos primeiro ver como isso funciona e, em seguida, analisar o comando. Criamos um diretório com oito arquivos, todos com nomes bem diferentes, exceto que sua extensão corresponde e é . pdf. Em seguida, executamos o comando acima:

O resultado foi que os 8 arquivos foram renomeados para 1. pdf, 2. pdf, 3. pdf, etc., embora seus nomes estivessem bastante deslocados antes.
O comando assume que você ainda não possui nenhum arquivo nomeado de 1. pdf a x. pdf. Se você fizer isso, poderá mover esses arquivos para um diretório separado, definir o eco 1 para um número maior para começar a renomear os arquivos restantes em um determinado deslocamento e, em seguida, mesclar os dois diretórios novamente.
Sempre tome cuidado para não sobrescrever nenhum arquivo e é sempre uma boa ideia fazer um backup rápido antes de atualizar qualquer coisa.
Vejamos o comando em detalhes. Pode ajudar a ver o que está acontecendo adicionando a opção -t a xargs, que nos permite ver o que está acontecendo nos bastidores:

Para começar, o comando usa dois pequenos arquivos temporários (chamados _e e _c) como armazenamento temporário. No início do oneliner, ele faz uma verificação de segurança usando uma instrução if para garantir que os arquivos _e e _c não estejam presentes. Se houver um arquivo com esse nome, o script não continuará.
Sobre o tópico de usar pequenos arquivos temporários versus variáveis, posso dizer que, embora o uso de variáveis fosse ideal (salva um pouco de E / S de disco), havia dois problemas que eu estava enfrentando.
O primeiro é que se você EXPORTAR uma variável no início do oneliner e depois usar a mesma variável mais tarde, se outro script usar a mesma variável (incluindo este script, execute mais em seguida, uma vez simultaneamente na mesma máquina), então esse script, ou este, pode ser afetado. É melhor evitar essa interferência quando se trata de renomear muitos arquivos!
O segundo foi que xargs em combinação com bash -c parece ter uma limitação na manipulação de variáveis dentro da linha de comando bash -c. Mesmo uma extensa pesquisa online não forneceu uma solução viável para isso. Assim, acabei usando um pequeno arquivo _c que mantém o progresso.
_e é a extensão que procuraremos e usaremos, e _c é um contador que aumentará automaticamente a cada renomeação. O eco $ [$ (cat _c) + 1] > O código _c cuida disso, exibindo o arquivo com cat, adicionando um número e reescrevendo-o.
O comando também usa o melhor método possível de tratamento de caracteres de nome de arquivo especial usando terminação nula em vez da terminação de nova linha padrão, ou seja, o caractere \ 0. Isso é garantido pela opção -print0 para localizar e pela opção -0 para xargs.
O comando find irá procurar qualquer arquivo com a extensão especificada no arquivo _e (criado pelo comando echo 'pdf' > _e. Você pode variar esta extensão para qualquer outra extensão que desejar, mas por favor não prefixe com um ponto. O ponto já está incluído no especificador *. $ (cat _e) -name posterior a ser encontrado.
Assim que encontrar localizou todos os arquivos e os enviou – \ 0 terminado em xargs, xargs renomeará os arquivos um por um usando o arquivo contador (_c) e o mesmo arquivo de extensão (_e). Para obter o conteúdo dos dois arquivos, um comando cat simples é usado, executado a partir de um subshell.
O comando mv move usa -n para evitar sobrescrever qualquer arquivo já presente. Por fim, limpamos os dois arquivos temporários removendo-os.
Embora o custo de usar dois arquivos de estado e bifurcação de subshell possa ser limitado, isso adiciona alguma sobrecarga ao script, especialmente ao lidar com uma grande quantidade de arquivos.
Existem muitos outros tipos de soluções para este mesmo problema online, e muitos tentaram e não conseguiram criar uma solução totalmente funcional. Muitas soluções esqueceram todos os tipos de casos colaterais, como usar ls sem especificar --color = never, o que pode fazer com que códigos hexadecimais sejam analisados quando o código de cores da lista de diretórios for usado.
Ainda outras soluções deixaram de lidar com arquivos com espaços, novas linhas e caracteres especiais como & # 8216; \ &’ corretamente. Para isso, a combinação find ... -print0 ... | xargs -0 ... geralmente é indicado e ideal (e ambos os manuais find e xargs fazem alusão a este fato fortemente).
Embora eu não considere minha implementação a solução perfeita ou final, ela parece fazer um avanço significativo para muitas das outras soluções por aí, usando find e \ 0 strings terminadas, garantindo o nome de arquivo máximo e compatibilidade de análise também como tendo algumas outras sutilezas, como ser capaz de especificar um deslocamento inicial e ser totalmente nativo do Bash.
Divirta-se!
Nenhum comentário