AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / unix / Perguntas / 718845
Accepted
Bussiere
Bussiere
Asked: 2022-09-27 22:22:47 +0800 CST2022-09-27 22:22:47 +0800 CST 2022-09-27 22:22:47 +0800 CST

Como renomear o arquivo com a extensão adequada quando não se sabe quais são?

  • 772

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 filecomando 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

linux files
  • 5 5 respostas
  • 216 Views

5 respostas

  • Voted
  1. dpat
    2022-10-05T08:24:04+08:002022-10-05T08:24:04+08:00

    Díficil. file(1)tem uma --extensionopção, mas nos meus testes (Debian/bullseye) a maioria dos arquivos mostrou pontos de interrogação ( ???).

    E a codificação case..esacpara cada tipo de arquivo conhecido provavelmente não funcionará, pois fileparece detectar pelo menos 3000 tipos de arquivo:

    ❯ file -l | wc -l
    3186
    

    Primeiro eu tentaria obter a lista dos tipos de arquivo no diretório fornecido:

    Observe, zsh-globbing usado aqui:

    ❯ file -p -n -b .*(.) *(.) | sort | uniq
    ASCII text
    ASCII text, with no line terminators
    ASCII text, with very long lines
    ASCII text, with very long lines, with no line terminators
    data
    empty
    JPEG image data, JFIF standard 1.01, resolution (DPI), density 300x300, segment length 16, Exif Standard: [TIFF image data, big-endian, direntries=0], baseline, precision 8, 96x96, components 3
    JSON data
    Non-ISO extended-ASCII text, with very long lines, with CRLF, LF line terminators, with escape sequences
    Python script, UTF-8 Unicode text executable
    UTF-8 Unicode text
    UTF-8 Unicode text, with very long lines
    very short file (no magic)
    X11 Xauthority data
    

    A findlinha a seguir leva à mesma saída:

    find -maxdepth 1 -type f -exec file -p -n -b {} \; | sort | uniq
    

    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:

    ext1;ASCII text
    ext2;ASCII text, with no line terminators
    ext3;ASCII text, with very long lines
    ext4;ASCII text, with very long lines, with no line terminators
    ext5;data
    ext6;empty
    ext7;JPEG image data, JFIF standard 1.01, resolution (DPI), density 300x300, segment length 16, Exif Standard: [TIFF image data, big-endian, direntries=0], baseline, precision 8, 96x96, components 3
    ext8;JSON data
    ext9;Non-ISO extended-ASCII text, with very long lines, with CRLF, LF line terminators, with escape sequences
    ext10;Python script, UTF-8 Unicode text executable
    ext11;UTF-8 Unicode text
    ext12;UTF-8 Unicode text, with very long lines
    ext13;very short file (no magic)
    ext14;X11 Xauthority data
    

    HTH

    • 2
  2. Stéphane Chazelas
    2022-10-08T03:30:26+08:002022-10-08T03:30:26+08:00

    Com perl-based renamee o File::MimeInfo::Magicmódulo perl (no libfile-mimeinfo-perlpacote em sistemas baseados em Debian, geralmente instalado por padrão em instalações de desktop, pois é uma dependência (recomendada) de xdg-utils):

    rename -n -- '
      use File::MimeInfo::Magic qw(mimetype extensions);
      my $ext; $_ .= ".$ext" if ! /\./ && ($ext = extensions mimetype$_)' *
    

    (remova o -npara execução a seco, se estiver correto).

    • 2
  3. zhaorong
    2022-10-04T00:09:51+08:002022-10-04T00:09:51+08:00

    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.

    • 1
  4. Best Answer
    Jim L.
    2022-10-06T12:48:09+08:002022-10-06T12:48:09+08:00

    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 bashshell.

    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:

    $ mkdir ~/my-backup
    $ rsync -av ./ ~/my-backup/
    

    Agora, se você errar alguma coisa, você pode restaurar a partir do seu backup:

    $ rsync -av --delete ~/my-backup/ ./
    

    filevaria muito

    A qualidade de implementação do filecomando varia entre as distribuições. Parece ser uma aposta segura que quanto mais recente o lançamento, melhor, já magicque o arquivo fileusado 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 do file.

    Então, quão boa é a fileimplementação do meu sistema?

    Vamos definir uma função fextque será executada file -b --extensionem qualquer glob curinga que dermos a ela. Além disso, executaremos a saída de algumas transformações filesimples para padronizar a saída ao nosso gosto:sedfile

    fext () {
      file -b --extension "$@" |
      sed -e 's-^jpeg/jpg/jpe/jfif$-jpg-' |
      sed -e 's-^pdf$-PDF-' |
      cat
    }
    

    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 a sedlinha para traduzir esses múltiplos para a única extensão de sua preferência, ou capitalizar arbitrariamente, se desejar, etc. Neste exemplo, os arquivos identificados filecomo as jpeg/jpg/jpe/jfifreceberão a extensão jpg, enquanto os arquivos identificados como pdfreceberão a extensão PDF. O caté 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 fileretorna várias extensões. Isso é simples de testar:

    $ fext * | grep /
    

    Não deve haver saída. Se houver saída, você precisará adicionar outra sedlinha à sua fextdefinição.

    Agora você pode executar fextem 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:

    $ fext * | sort | uniq -c
    

    Ubuntu 18.04.2 LTS:

    $ fext * | sort | uniq -c
        137 ???
         15 jpg
    

    FreeBSD 13.1:

    $ fext * | sort | uniq -c
      28 ???
      76 PDF
      15 jpg
      32 png
       1 tif,tiff
    

    Ubuntu 22.04 LTS:

    $ fext * | sort | uniq -c
         28 ???
         15 jpg
         76 PDF
         32 png
          1 tif,tiff
    

    Observe que encontramos um bug no magicarquivo usado pelo fileutilitário. Felizmente, isso é fácil de corrigir em nossa fextfunção:

    $ fext () {
      file -b --extension "$@" |
      sed -e 's-^jpeg/jpg/jpe/jfif$-jpg-' |
      sed -e 's-^pdf$-PDF-' |
      sed -e 's-^tif,tiff$-tiff-' |
      cat
    }
    $ fext * | sort | uniq -c
         28 ???
         15 jpg
         76 PDF
         32 png
          1 tiff
    

    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, filenão identifica 28 dos 152 arquivos, ou um pouco mais de 18%. Podemos refinar ainda mais nossa fextfunção para atribuir uma extensão padrão a arquivos desses tipos que filenão podem ser identificados.

    $ fext () {
      file -b --extension "$@" |
      sed -e 's-^jpeg/jpg/jpe/jfif$-jpg-' |
      sed -e 's-^pdf$-PDF-' |
      sed -e 's-^tif,tiff$-tiff-' |
      sed -e 's-^???$-unknown-' |
      cat
    }
    $ fext * | sort | uniq -c
         15 jpg
         76 PDF
         32 png
          1 tiff
         28 unknown
    

    Se desejarmos, podemos greplistar e ver os nomes de arquivos específicos dos arquivos que file não conseguem identificar:

    $ for f in *; do [ -f "$f" ] && printf '%10s %s\n' "$(fext "$f")" "$f"; done | grep -w unknown 
    

    No meu (fraco) conjunto de amostras, os arquivos "desconhecidos" são predominantemente arquivos PostScript. fileos identifica como tal, mas o magicarquivo não tem uma extensão designada para arquivos PostScript.

    Então, se usarmos fextpara fornecer a extensão para cada arquivo, os arquivos que filenão conseguirem identificar receberão a extensão unknown.

    $ for f in *; do [ -f "$f" ] && mv -vi "$f" "$f.$(fext "$f")"; done
    
    • 1
  5. xiota
    2022-10-08T01:41:03+08:002022-10-08T01:41:03+08:00

    Infelizmente, file -b --extensionnã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:

    # using hard links
    cp --link /path/to/originals /path/to/files
    
    # using reflinks on supported file systems
    cp --reflink=auto /path/to/originals /path/to/files
    

    Em seguida, crie uma lista de tipos mime no diretório:

    find /path/to/files -type f -exec file -b --mime-type {} \; | sort -u
    

    A saída se parece com:

    application/epub+zip
    application/msword
    application/pdf
    application/zip
    image/gif
    image/jpeg
    image/png
    image/svg+xml
    text/html
    text/plain
    text/rtf
    text/xml
    

    Agora crie um bashscript add_ext.shque renomeie os arquivos com a extensão apropriada, de acordo com o tipo mime, se necessário.

    #!/usr/bin/env bash
    
    [ $# -lt 1 ] && echo "Usage: $0 <FILE>" && exit 1
    
    mimetype=$(file -b --mime-type "$1")
    extension="${1#**.}"
    new_ext="unset"
    
    case $mimetype in
       'application/epub+zip')
          new_ext="epub"
          ;;
    
       'application/msword')
          new_ext="doc"
          ;;
    
       'application/pdf')
          new_ext="pdf"
          ;;
    
       'application/zip')
          new_ext="zip"
          ;;
    
       'image/gif')
          new_ext="gif"
          ;;
    
       'image/jpeg')
          new_ext="jpeg"
          ;;
    
       'image/png')
          new_ext="png"
          ;;
    
       'image/svg+xml')
          new_ext="svg"
          ;;
    
       'text/html')
          new_ext="html"
          ;;
    
       'text/plain')
          new_ext="txt"
          ;;
    
       'text/rtf')
          new_ext="rtf"
          ;;
    
       'text/xml')
          new_ext="xml"
          ;;
    esac
    
    [ "$new_ext" != "unset" ] \
       && [ "$extension" != "$new_ext" ] \
       && [ ! -e "$1.$new_ext" ] \
       && mv "$1" "$1.$new_ext"
    

    Não esqueça chmod +x add_ext.shantes de usar findpara executar o script nos arquivos:

    find /path/to/files -type f -exec ./add_ext.sh {} \;
    
    • 0

relate perguntas

  • Inicie/pare o serviço systemd usando o atalho de teclado [fechado]

  • du/df e ls relatando diferentes usos de disco

  • Necessidade de algumas chamadas de sistema

  • astyle não altera a formatação do arquivo de origem

  • Passe o sistema de arquivos raiz por rótulo para o kernel do Linux

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    Possível firmware ausente /lib/firmware/i915/* para o módulo i915

    • 3 respostas
  • Marko Smith

    Falha ao buscar o repositório de backports jessie

    • 4 respostas
  • Marko Smith

    Como exportar uma chave privada GPG e uma chave pública para um arquivo

    • 4 respostas
  • Marko Smith

    Como podemos executar um comando armazenado em uma variável?

    • 5 respostas
  • Marko Smith

    Como configurar o systemd-resolved e o systemd-networkd para usar o servidor DNS local para resolver domínios locais e o servidor DNS remoto para domínios remotos?

    • 3 respostas
  • Marko Smith

    apt-get update error no Kali Linux após a atualização do dist [duplicado]

    • 2 respostas
  • Marko Smith

    Como ver as últimas linhas x do log de serviço systemctl

    • 5 respostas
  • Marko Smith

    Nano - pule para o final do arquivo

    • 8 respostas
  • Marko Smith

    erro grub: você precisa carregar o kernel primeiro

    • 4 respostas
  • Marko Smith

    Como baixar o pacote não instalá-lo com o comando apt-get?

    • 7 respostas
  • Martin Hope
    user12345 Falha ao buscar o repositório de backports jessie 2019-03-27 04:39:28 +0800 CST
  • Martin Hope
    Carl Por que a maioria dos exemplos do systemd contém WantedBy=multi-user.target? 2019-03-15 11:49:25 +0800 CST
  • Martin Hope
    rocky Como exportar uma chave privada GPG e uma chave pública para um arquivo 2018-11-16 05:36:15 +0800 CST
  • Martin Hope
    Evan Carroll status systemctl mostra: "Estado: degradado" 2018-06-03 18:48:17 +0800 CST
  • Martin Hope
    Tim Como podemos executar um comando armazenado em uma variável? 2018-05-21 04:46:29 +0800 CST
  • Martin Hope
    Ankur S Por que /dev/null é um arquivo? Por que sua função não é implementada como um programa simples? 2018-04-17 07:28:04 +0800 CST
  • Martin Hope
    user3191334 Como ver as últimas linhas x do log de serviço systemctl 2018-02-07 00:14:16 +0800 CST
  • Martin Hope
    Marko Pacak Nano - pule para o final do arquivo 2018-02-01 01:53:03 +0800 CST
  • Martin Hope
    Kidburla Por que verdadeiro e falso são tão grandes? 2018-01-26 12:14:47 +0800 CST
  • Martin Hope
    Christos Baziotis Substitua a string em um arquivo de texto enorme (70 GB), uma linha 2017-12-30 06:58:33 +0800 CST

Hot tag

linux bash debian shell-script text-processing ubuntu centos shell awk ssh

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve