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 / 700865
Accepted
Niklas Rosencrantz
Niklas Rosencrantz
Asked: 2022-04-30 07:49:45 +0800 CST2022-04-30 07:49:45 +0800 CST 2022-04-30 07:49:45 +0800 CST

programa diff dá falso positivo para arquivos com caracteres não ASCII no nome do arquivo

  • 772

Exemplo:

% diff "/Volumes/New Volume/4kyoutube/" "/Volumes/New Volume/tmpmusic"| grep Distortion
Only in /Volumes/New Volume/tmpmusic: ZAC & Bäkka - Distortion (Original Mix) [Sprout].mp3
Only in /Volumes/New Volume/4kyoutube/: ZAC & Bäkka - Distortion (Original Mix) [Sprout].mp3

% diff "/Volumes/New Volume/tmpmusic/ZAC & Bäkka - Distortion (Original Mix) [Sprout].mp3" "/Volumes/New Volume/4kyoutube/ZAC & Bäkka - Distortion (Original Mix) [Sprout].mp3" 
% 

O que posso fazer sobre isso? Os arquivos são idênticos.

diff macos
  • 2 2 respostas
  • 340 Views

2 respostas

  • Voted
  1. Best Answer
    LSerni
    2022-04-30T08:21:22+08:002022-04-30T08:21:22+08:00

    Este não é um "diff falso positivo", mas os dois nomes de arquivo são vistos como diferentes .

    Minha hipótese selvagem é que as duas pastas estão em dispositivos diferentes, com uma codificação de arquivo diferente; ou que os dois nomes são codificados de forma diferente , embora sejam visualmente idênticos. Especificamente, um dos dois "Bäkka" está na forma "pré-composta", ou seja, U+00E4 (UTF-8 C3 A4), enquanto o outro está na forma "decomposta", U+0061 U+0308 (UTF-8 0x61 0xCC 0x88) com trema de combinação.

    Não tenho um MacOS em mãos, mas posso reproduzir isso em um Linux ext4:

    $ A=$( echo -e "Ba\xcc\x88kka" )
    $ B=$( echo -e "B\xc3\xa4kka" )
    $ echo $A $B
    Bäkka Bäkka
    $ touch $A $B
    $ ls -la | grep kka
    -rw-rw-rw-+  1 lserni  users     0 Apr 29 18:14 Bäkka
    -rw-rw-rw-+  1 lserni  users     0 Apr 29 18:14 Bäkka
    

    Aparentemente, agora tenho dois arquivos com o mesmo nome na mesma pasta .

    Obviamente, não posso ter certeza, mas você pode estar na mesma situação.

    Para verificar, basta executar a saída de "diff" hexdump -Ce ver se você tem algo como,

    00000020  20 20 20 30 20 41 70 72  20 32 39 20 31 38 3a 31  |   0 Apr 29 18:1|
    00000030  36 20 42 61 cc 88 6b 6b  61 0a 2d 72 77 2d 72 77  |6 Ba..kka.-rw-rw|
    00000060  70 72 20 32 39 20 31 38  3a 31 36 20 42 c3 a4 6b  |pr 29 18:16 B..k|
    00000070  6b 61 0a                                          |ka.|
    

    Observe que no despejo hexadecimal eles são imediatamente visíveis como "Ba..kka" (o "a" é um "a" normal, seguido pelo UTF8 "adicionar um trema") e "B..kka" (há apenas um símbolo e é "pequeno latino a com trema").

    Consertando coisas

    Francamente, eu executaria primeiro uma normalização em toda a estrutura de pastas. Mesmo se você tiver arquivos com nomes idênticos, mas com uma codificação diferente (ou seja, alguns pré-compostos, alguns decompostos), isso vai te morder mais cedo ou mais tarde.

    Do ponto de vista do sistema de arquivos, qual sistema você usa é irrelevante. O importante é como você alimenta o sistema agora e como você usa o sistema agora.

    Se os novos arquivos de entrada tiverem nomes pré-compostos, faz sentido definir todos os FS como pré-compostos (ou vice-versa), para que o padrão seja mantido. Por outro lado, você também pode querer verificar funções como pesquisar arquivos, classificar e assim por diante, para verificar se os arquivos estão onde você espera que estejam (desnecessário dizer que alguns sistemas consideram "a", "ä " e "ä" o mesmo, alguns outros não - eles podem definir "a" e "ä" juntos, "ä" em outro lugar; ou vice-versa).

    Eu tentaria copiar um pequeno arquivo mp3 com os nomes "älpha composto", "älpha decomposed" e "alpha neutro", depois trabalhar com uma pasta com esses três arquivos, bem como "alpha 0 test" e "alpha z test" , e então se decomposto ou pré-composto é o melhor, se houver.

    Os documentos parecem indicar que você deve usar arquivos .

    Então, em primeiro lugar, você precisa de uma lista de todos os nomes de arquivos. Isso é facil

    find . -type f > list-as-it-is.txt
    

    Mas agora você precisa converter os elementos pré-compostos na lista para sua forma decomposta. Eu fiz um pouco de pesquisa e, para adicionar mais uma camada de complicação, parece que o MacOS e o Linux se comportam de maneira diferente , e o MacOS tem vários problemas de acomodação herdados:

    Importante: Os termos usados ​​nesta Q&A, pré-compostos e decompostos, correspondem aproximadamente às Formas Normais Unicode C e D, respectivamente. No entanto, a maioria dos formatos de volume não segue a especificação exata para essas formas normais. Por exemplo, HFS Plus (Mac OS Extended) usa uma variante da Forma Normal D na qual U+2000 a U+2FFF, U+F900 a U+FAFF e U+2F800 a U+2FAFF não são decompostos (isso evita problemas com conversões de ida e volta de antigas codificações de texto do Mac). É provável que o formato do seu volume tenha estranhezas semelhantes.

    Em teoria, você deve ter apenas um formulário no disco ("A camada BSD do Mac OS X usa codificação UTF-8 decomposta canonicamente para nomes de arquivos"). Na prática, parece depender (obviamente, caso contrário você não teria problemas; previsivelmente, você não está sozinho ).

    Então, sou muito cauteloso em sugerir um método de conversão sem poder testá-lo de antemão em um MacOS real. Se os arquivos forem poucos, sugiro corrigi-los manualmente - exclua um arquivo e copie o outro na outra pasta.

    Em teoria , você poderia fazer algo como (no Bash)

    hexa=$( echo -n "$name" | xxd -ps | tr -d "\n" )
    if [ $[ 2*${#name} ] -lt ${#hexa} ]; then
        # Not ASCII.
    

    ou if ( echo "$name" | file - | grep "UTF-8" > /dev/null ); então

    e se o teste corresponder, você pode fazer

    mv "$name" "$(dirname "$name")/tmpname" && mv "$(dirname "$name")/tmpname" "$name"
    

    e talvez o primeiro "mv" reconheça o arquivo qualquer que seja sua codificação, enquanto o segundo recrie o nome usando a codificação padrão fixa do sistema, que esperamos que seja adequada para você.

    Esse tipo de operação seria muito rápido, mesmo que processasse desnecessariamente todos os nomes UTF-8.

    Ignorando coisas

    Você pode ignorar todos os arquivos com esse tipo de truque. Então, o problema surgiria apenas quando dois arquivos fossem diferentes e tivessem o mesmo nome codificado de forma diferente . Isso é um problema? Se não for, então está tudo pronto.

    Basta fazer uma preliminar greppara remover as linhas contendo "^Only":

    diff ... | grep -v ^Only | grep Distortion
    

    Removendo duplicatas

    Isso, felizmente, ignora totalmente a codificação. Existem ferramentas que já fazem isso ( jdupesé a que eu uso). Arquivos com conteúdo idêntico que diferem por tags MP3 não funcionarão com essa abordagem e você provavelmente achará essa resposta útil.

    find folder1 -type f -exec md5sum \{\} \; | sort > folder1.txt
    find folder2 -type f -exec md5sum \{\} \; | sort > folder2.txt
    

    Agora, se você quiser obter duplicatas:

    join -o 2.2 folder1.txt folder2.txt
    

    obterá os arquivos na pasta2 que são duplicados (-o 2.1 obterá os arquivos na pasta1).

    • 10
  2. Stilez
    2022-04-30T17:09:53+08:002022-04-30T17:09:53+08:00

    Agora que @LSerni descobriu a questão do que está acontecendo, você ainda precisa lidar com a forma de contornar isso.

    Claramente, alguma renomeação canônica ou pelo menos consistente é a melhor. Mas você pode não conseguir, ou pode acontecer com novos arquivos. Portanto, precisamos de uma solução alternativa aprimorada.

    O que eu faria é evitar completamente o espinhoso problema do Unicode.

    Eu executaria o diretório inteiro por meio de sha512() ou alguma outra função de hash (recursiva, se necessário). Então, eu usaria isso para reconhecer arquivos com o mesmo conteúdo, mesmo que os nomes sejam diferentes. Com efeito, criando artificialmente para fins de diff, um equivalente de nome de arquivo canônico (por meio de links simbólicos ou uma matriz programática de caminhos/hashes), ou filtrando a saída de diff, ou executando diff em várias passagens, ou substituindo sua própria lógica para relatar equivalência de arquivo incerta mas antes combinando por hash para sugerir equivalentes .....

    Em outras palavras, há várias maneiras de fazer isso, e deve ser muito fácil ... mas não posso sugerir qual maneira funciona para você, pois não está claro seu objetivo preciso ao diferenciá-las, nem sua habilidade de codificação.

    • 3

relate perguntas

  • Diff nomes de arquivos de dois diretórios?

  • Usando a saída de diff -e com sed

  • diff de arquivos de configuração mostrando apenas linhas não comentadas

  • Determine se duas imagens iso são iguais

  • git: use visual diff (meld) somente quando estiver na GUI

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