No macOS e com o sistema de arquivos HFS +, pelo menos, caracteres acentuados são codificados em sua forma decomposta, então à
é codificado como a\u300
( a
seguido pelo combinando acento grave < href="https://en.wikipedia.org/wiki/Combining_character"> combinando caractere ) mesmo se você criou o arquivo com touch $'\ue0'
(o formulário pré-composto (autônomo a
com sotaque grave), causando todos os tipos de bugs (e sujeito de uma das famosas declarações de Linus Torvald ) como por seu pseudo insensibilidade de caixa.
Você notará que, se fizer isso:
touch à; echo ?
para listar os nomes dos arquivos feitos de um caractere, ele não retorna nada enquanto:
echo ??
ou
echo *a*
Retorna esse à
(na verdade, à
). E:
$ echo ?? | uconv -x name
\N{LATIN SMALL LETTER A}\N{COMBINING GRAVE ACCENT}\N{<control-000A>}
Então você precisaria:
rename $'s/a\u300/a/g' ./*
(assumindo zsh
ou shell compatível). Ou usando especificando a codificação UTF-8 daquele caractere U + 0300 (0xcc 0x80) manualmente, para shells que suportam o ksh93 $'...'
quotes, mas não zsh
' $'\u300'
(como a versão antiga de bash
encontrado no macOS):
rename $'s/a\xcc\x80/a/g' ./*
Ou deixe que perl
interprete essas sequências \xcc\x80
diretamente:
rename 's/a\xcc\x80/a/g' ./*
Ou o caractere unicode:
PERL_UNICODE=AS rename 's/\x{300}//' ./*
Ou remova todos os caracteres combinados com:
PERL_UNICODE=AS rename -n 's/\pM//g' ./*
Lá, estamos dizendo que perl
considera A
rguments e S
tdio streams são codificados em UTF-8 (consulte perldoc perlrun
para obter uma descrição do $PERL_UNICODE
env var equivalente ao -C
option) e remova todos os caracteres que têm M
ark Unicode p
roperty ( \pM
é a abreviação de \p{Mark}
ou \p{Combining_Mark}
, consulte perldoc perluniprops
para obter detalhes)
Note que você deve poder listar esse arquivo (em zsh
) com os dois:
ls -d $'a\u300'
e:
ls -d $'\ue0'
(e $'A\u300' and possibly $'\uc0
para À
, pois ele não diferencia maiúsculas de minúsculas), mas:
ls -d *A*
e em shells que não sejam zsh
:
ls -d *$'\ue0'*
ls -d *$'\xc3\xa0'*
não corresponde, porque o shell lista o conteúdo do diretório atual e aplica o padrão a cada nome de arquivo, e o nome do arquivo é codificado como a\u300
, o que não coincide.
Em zsh
, no entanto, e no macOS apenas, o shell converte internamente essas letras com acentos de combinação para seu formulário pré-composto em readdir()
, como se estivesse passando-as por iconv -f UTF-8-MAC -t UTF-8
. Seu próprio wrapper zreaddir()
interno em torno de readdir()
não retorne U + 00E0 em vez de aU+0300
, o que explica por que echo *à*
trabalha lá (e não echo *a*
) e não em outro lugar.
A alteração foi introduzida em junho de 2014. Consulte a discussão na lista de discussão zsh para obter mais detalhes .
O núcleo do problema é a discrepância entre a codificação usada na entrada do usuário e aquela usada para armazenar (e listar) nomes de arquivos no sistema de arquivos. O problema é muito pior em coreano, onde praticamente todos os personagens têm um formulário pré-composto e decomposto, o que explica por que a questão do zsh foi levantada inicialmente por uma pessoa coreana.
Portanto, zsh
corrige a má escolha da Apple de forma decomposta no sistema de arquivos para que sua conclusão e globs possam ser usados, mas infelizmente isso se aplica apenas a zsh
, ls | grep à
ou find . -name '*à*'
ainda não funcionará.