Tenho cerca de 100.000 arquivos em um diretório sem extensão, não sei quais são alguns parecem ser pdf, jpg, png , xls etc...
Existe uma maneira simples de adicionar a extensão para cada arquivo?
Minha ideia atual é fazer um script que para cada arquivo faça um file
comando nele, obtenha o resultado com um grep (como grep png) com um if e adicione png se for verdade.
Se alguém tiver um método melhor.
Cumprimentos
Díficil.
file(1)
tem uma--extension
opção, mas nos meus testes (Debian/bullseye) a maioria dos arquivos mostrou pontos de interrogação (???
).E a codificação
case..esac
para cada tipo de arquivo conhecido provavelmente não funcionará, poisfile
parece detectar pelo menos 3000 tipos de arquivo:Primeiro eu tentaria obter a lista dos tipos de arquivo no diretório fornecido:
Observe, zsh-globbing usado aqui:
A
find
linha a seguir leva à mesma saída:Com esta lista, eu criaria um tipo de arquivo de mapeamento/pesquisa de extensão de tipo de arquivo e o usaria para renomear os arquivos:
HTH
Com
perl
-basedrename
e oFile::MimeInfo::Magic
módulo perl (nolibfile-mimeinfo-perl
pacote em sistemas baseados em Debian, geralmente instalado por padrão em instalações de desktop, pois é uma dependência (recomendada) dexdg-utils
):(remova o
-n
para execução a seco, se estiver correto).Adivinhar o tipo de arquivo de acordo com o número mágico pode ajudar a resolver isso.
Consulte https://en.wikipedia.org/wiki/List_of_file_signatures
Esta página lista a maioria dos tipos de arquivos e seus números mágicos, seu script apenas lê alguns bytes do deslocamento e compara com a assinatura e adiciona o sufixo correspondente.
Esta resposta pressupõe que você tenha uma lista relativamente limpa de nomes de arquivos, todos em um diretório, e que os nomes dos arquivos não contenham espaços, tabulações, novas linhas e outros caracteres mal comportados. Os trechos de código aqui são destinados ao
bash
shell.Primeiro, faça um backup
Sempre que você está fazendo uma renomeação automática de milhares de arquivos, sempre há uma chance de haver um problema. Um problema vezes cem mil arquivos equivale a cem mil problemas a serem corrigidos antes que você possa tentar novamente.
Comece fazendo um backup:
Agora, se você errar alguma coisa, você pode restaurar a partir do seu backup:
file
varia muitoA qualidade de implementação do
file
comando varia entre as distribuições. Parece ser uma aposta segura que quanto mais recente o lançamento, melhor, jámagic
que o arquivofile
usado provavelmente será mais atualizado. Se puder, você pode obter resultados mais completos (ou seja, menos trabalho manual) copiando/rsync
-ing os arquivos para uma máquina executando um sistema operacional com uma versão melhor dofile
.Então, quão boa é a
file
implementação do meu sistema?Vamos definir uma função
fext
que será executadafile -b --extension
em qualquer glob curinga que dermos a ela. Além disso, executaremos a saída de algumas transformaçõesfile
simples para padronizar a saída ao nosso gosto:sed
file
Por favor, perdoe os inúteis
cat
. Ele está incluído para modularidade, de modo que, se você tiver tipos de arquivo que retornam várias strings de extensão, você pode copiar, colar e editar ased
linha para traduzir esses múltiplos para a única extensão de sua preferência, ou capitalizar arbitrariamente, se desejar, etc. Neste exemplo, os arquivos identificadosfile
como asjpeg/jpg/jpe/jfif
receberão a extensãojpg
, enquanto os arquivos identificados comopdf
receberão a extensãoPDF
. Ocat
é apenas um espaço reservado no-op no final da lista de transformação.E quanto a outros tipos de arquivo que possuem várias extensões?
É importante garantir que você enumerou todos os tipos de arquivo possíveis em sua coleção para os quais
file
retorna várias extensões. Isso é simples de testar:Não deve haver saída. Se houver saída, você precisará adicionar outra
sed
linha à suafext
definição.Agora você pode executar
fext
em toda a sua coleção de arquivos para ver quantos ele acha que reconhece e quantos não reconhece.Estou usando um grupo de teste de 152 arquivos fracamente escolhidos. Em três sistemas, eu corri:
Ubuntu 18.04.2 LTS:
FreeBSD 13.1:
Ubuntu 22.04 LTS:
Observe que encontramos um bug no
magic
arquivo usado pelofile
utilitário. Felizmente, isso é fácil de corrigir em nossafext
função:Excelente. O importante aqui é que NÃO há barras (ou vírgulas!). Criamos uma métrica quantitativa bruta que nos permite ver qual porcentagem de arquivos são identificados por
file
. Especificamente,file
não identifica 28 dos 152 arquivos, ou um pouco mais de 18%. Podemos refinar ainda mais nossafext
função para atribuir uma extensão padrão a arquivos desses tipos quefile
não podem ser identificados.Se desejarmos, podemos
grep
listar e ver os nomes de arquivos específicos dos arquivos quefile
não conseguem identificar:No meu (fraco) conjunto de amostras, os arquivos "desconhecidos" são predominantemente arquivos PostScript.
file
os identifica como tal, mas omagic
arquivo não tem uma extensão designada para arquivos PostScript.Então, se usarmos
fext
para fornecer a extensão para cada arquivo, os arquivos quefile
não conseguirem identificar receberão a extensãounknown
.Infelizmente,
file -b --extension
não é muito útil porque retorna???
para muitos formatos com extensões conhecidas. Em vez disso, comece clonando o diretório de interesse em caso de algum contratempo:Em seguida, crie uma lista de tipos mime no diretório:
A saída se parece com:
Agora crie um
bash
scriptadd_ext.sh
que renomeie os arquivos com a extensão apropriada, de acordo com o tipo mime, se necessário.Não esqueça
chmod +x add_ext.sh
antes de usarfind
para executar o script nos arquivos: