Qual é uma maneira eficaz de anexar automaticamente extensões de arquivo a arquivos sem extensão?

Qual é uma maneira eficaz de anexar automaticamente extensões de arquivo a arquivos sem extensão?

Eu escrevi um script bash hoje durante meu horário de almoço que encontra arquivos sem extensão em um diretório e anexa uma extensão de arquivo a esses arquivos.

O script é relativamente longo porque adicionei um monte de sinalizadores e coisas como seleção de diretório e se devo copiar ou sobrescrever o arquivo, mas a essência de sua funcionalidade pode ser replicada simplesmente com isto:

#recursively find files in current directory that have no extension
for i in $(find . -type f ! -name "*.*"); do
    #guess that extension using file
    extfile=$(file --extension --brief $i)
    #select the first extension in the event file spits something weird (e.g. jpeg/jpe/jfif) 
    extawk=$(echo $extfile | awk -F/ '{print $1}')
    #copy the file to a file appended with the extension guessed from the former commands
    cp -av $i $i.$extawk
done

É um pouco mais organizado no meu script atual - eu só queria dividir os comandos aqui para poder comentar por que estava fazendo as coisas.

Minha pergunta: Usar findem combinação com fileda maneira que escolhi provavelmente não é a maneira mais infalível de fazer isso - qual é o problema?melhormaneira de adivinhar e acrescentar recursivamente extensões para um grupo em massa de diversos tipos de arquivos entre vários diretórios?

Responder1

for x in $(find …)falha comnomes de arquivos contendo espaços em branco (comuns) ou caracteres curinga (um tanto incomuns). Nunca analise a saída de find. Usar -exec.

Zshdezmvé conveniente para renomeação em massa.

Vamos construir um comando zmv que faça o que você deseja. Primeiro, vamos construir o padrão de pesquisa:

autoload zmv
zmv -C -o -a -n -Q '(*/)#^*.*(.)' …
  • -Cfaz com que os arquivos sejam copiados em vez de movidos.
  • -o -apassa -apara cp.
  • -nsignifica não agir, apenas imprimir o que seria feito. Remova-o quando estiver satisfeito. Substitua por -vse quiser agir, mas também imprimir o que está sendo feito.
  • -Qhabilitaeliminatórias globaisno padrão.
  • (*/)#corresponde a zero ou mais diretórios. Ele usa o# operador global( extended_globestá sempre habilitado no zmv).
  • ^*.*usa o ^operador glob para combinar arquivos sem a .no nome.
  • (.)é um qualificador global que restringe as correspondências a arquivos regulares.
  • será substituído pelo texto de substituição. Isso pode ser usado $fpara se referir ao nome original.

zmvcalcula todos os nomes substitutos antes de realizar qualquer substituição e reclamará se já existir algum nome substituto ou se houver conflitos. Os arquivos cujo nome substituto é idêntico ao original são ignorados.

Agora vamos construir o texto de substituição. Usaremos muitoexpansão de parâmetroscaracterísticas.

  1. Solicite filea extensão:$(file --extension --brief -- $f)
  2. Anexe um ., em preparação para a substituição: $(echo -n .; file --extension --brief -- $f)
    (Isso poderia ser feito alternativamente com a expansão do parâmetro: ${:-.$(…)}.)
  3. Se houver diversas extensões sugeridas (separadas por barras), mantenha apenas a primeira:${$(echo -n .; file --extension --brief -- $f)%%/*}
  4. Se a extensão sugerida estiver vazia ou ???, desista (substitua .ou .???por uma string vazia):${${$(echo -n .; file --extension --brief -- $f)%%/*}:#.(|\?\?\?)}
  5. Anexe a extensão adicionada a $f(o nome original). Se o que estamos anexando estiver vazio, o arquivo permanecerá intacto.

O comando resultante:

zmv -C -o -a -n -Q '(*/)#^*.*(.)' '$f${${$(echo -n .; file --extension --brief -- $f)%%/*}:#.(|\?\?\?)}'

Isso é um pouco enigmático e você pode preferir colocar o código para gerar a substituição em uma função e usar zmv … '$(add_extension $f)'.

Responder2

Acho que a maneira mais eficaz é comparar os tipos MIME do arquivo com o banco de dados localizado em /usr/share/mime/globs.

  • globosno Linux sãoextensão de arquivo. Exemplo dado, saída dearquivo globs
application/x-mswinurl:*.url
text/x-mrml:*.mrl
text/x-erlang:*.erl
audio/x-pn-audibleaudio:*.aa
application/x-bzip-compressed-tar:*.tbz2
application/x-netshow-channel:*.nsc
application/x-hdf:*.h4
application/pgp-keys:*.key
text/x-idl:*.idl
text/x-chdr:*.h
application/vnd.ms-powerpoint.presentation.macroEnabled.12:*.pptm
application/vnd.ms-powerpoint.presentation.macroEnabled.12:*.pptm
application/vnd.visio:*.vsd
application/x-hdf:*.h5
video/vnd.mpegurl:*.m4u
  • depois de descrever o tipo exemplo --> text/x-erlang, ele diz ao Linux para identificar todos os arquivos *.comoErlangcom extensão .erl[glob], é por isso ->*.erl
  • você pode adicionar suas próprias extensões para serem contabilizadas no /etc/magicarquivo

então executando o comando:

mimetype -bM file
  • bargumento para apenas mostrar a você type-app/extension(breve)

  • Margumento significaMagiaé a maneira como o Linux verifica o arquivo em código de bytes, hexadecimal, binário para verificar se os arquivos são realmente o que afirmam ser.

  • tipo MIMEnão retorna /jpg/png/webpapenas retorna um tipo e é menor quefile --mime-type file

Retorna:

image/webp

pensamentos finais

mimetypefunciona melhor comarquivos binárioscomo PDFs, imagens, vídeos. Isso porque ele pode verificar o binário, ao invés disso, text plainé só isso, e você precisa se identificar com alguma coisa, e isso é mais complicado, é por isso que editores de texto podem reconhecer diferentes linguagens de programação, ele precisa da ajuda do usuário e de uma linguagem de servidor para cada linguagem de programação.

para recursão, eu achoárvoreestá bem:

tree -FIi '*.*' | grep -v /$
  • argumento Fé adicionar /[barra] aos diretórios, por exemplo, folderfolder/
  • argumento Ié selecionar o oposto do padrão *.*[isso significa selecionar todos os arquivos com extensão], então o oposto não é extensão
  • argumento ié remover espaços da saída da árvore
  • grep -vé selecionar reverso, é por isso que você adiciona o /argumento -F aárvorecomando no início, para que você possa remover diretórios e obter apenas arquivos, com /$.

Confira mais aquitipos de mímica

informação relacionada