Eu tenho uma estrutura de pastas profunda em uma máquina Debian onde os nomes de diretórios e nomes de arquivos contêm alguns caracteres "especiais" ( ä
, ö
, ü
). No entanto, eles não estão em "ISO-8859-1", mas em formato de caracteres combinados Unicode. Então, como aprendi, isso é simples, a
juntamente com os dois pontos (diérese/trema) como caracteres "separados".
Tentei renomear em massa todos os arquivos e pastas usando find e sed:
#!/bin/bash
# Files - normal characters
find . -depth -name "*[äöüÄÖÜ]*" -exec bash -c 'mv "$1" "$(echo $1 | sed -e "s/ä/ae/g; s/ö/oe/g; s/ü/ue/g; s/Ä/Ae/g; s/Ö/Oe/g; s/Ü/Ue/g")"' _ {} \;
# Files - Unicode combining characters
find . -depth -name "*[äöüÄÖÜ]*" -exec bash -c 'mv "$1" "$(echo $1 | sed -e "s/ä/ae/g; s/ö/oe/g; s/ü/ue/g; s/Ä/Ae/g; s/Ö/Oe/g; s/Ü/Ue/g")"' _ {} \;
# Directories - normal characters
find . -depth -type d -name "*[äöüÄÖÜ]*" -exec bash -c 'mv "$1" "$(echo $1 | sed -e "s/ä/ae/g; s/ö/oe/g; s/ü/ue/g; s/Ä/Ae/g; s/Ö/Oe/g; s/Ü/Ue/g")"' _ {} \;
# Directories - Unicode combining characters
find . -depth -type d -name "*[äöüÄÖÜ]*" -exec bash -c 'mv "$1" "$(echo $1 | sed -e "s/ä/ae/g; s/ö/oe/g; s/ü/ue/g; s/Ä/Ae/g; s/Ö/Oe/g; s/Ü/Ue/g")"' _ {} \;
No entanto, parece que find
também seleciona todas as ocorrências de a
um nome de arquivo/pasta se o ä
parâmetro -name
for um Unicode combinado ä
em vez de ISO-8859-1. Por exemplo,
$ find . -name "*[ä]*" //<-- one letter ä
./filename_one_letter_ä
$ find . -name "*[ä]*" //<-- combining letter ä
./filename_with_just_a
./filename_one_letter_ä
./filename_with_combining_diaeresis_ä
Portanto, o sed
está passando os nomes dos arquivos inalterados e reclama mv
quando peço para renomeá-lo, por exemplo, “ Baustand
” para “ Baustand
” (ou seja, origem e destino são iguais).
Como posso pesquisar e substituir todos os Unicode combinados ä
, ö
, ü
, Ä
, Ö
, Ü
em uma estrutura de arquivo/pasta em um sistema Linux se não consigo procurá-los com find? Existe outra abordagem que eu poderia tentar?
Um exemplo dos meus nomes de arquivos e diretórios é:
/Projekte/03-11_Törggel_Mammern/Baustand/03-11_Törggel-Baustand_190501_0009.jpg
Que eu gostaria de renomear para
/Projekte/03-11_Toerggel_Mammern/Baustand/03-11_Toerggel-Baustand_190501_0009.jpg
A saída de echo $LANG
é en_US.UTF-8
.
Não consigo reproduzir este (ou mesmo testá-lo) ATM, mas…
Bem, você sabe que
[xyz]
correspondex
a ory
orz
. Eu acho que, quando você diz[äöü…]
(usando os caracteres combinados), está vendoa
¨
o
¨
u
¨
e assim encontra arquivos cujos nomes incluem
a
,o
,u
ou (combinando)¨
, mas não necessariamenteä
,ö
ouü
.Então tente procurá-los separadamente:
(sem colchetes). Observe que seu
echo $1
(sem aspas) pode falhar em alguns nomes de arquivos. (';'
é equivalente a\;
; prefiro evitar barras invertidas estilisticamente.)Ou, se você realmente quiser fazer tudo em um comando, tente
(
printf "%s"
é funcionalmente muito semelhante aecho
, mas mais seguro. Estilisticamente, eu normalmente usariaprintf '%s'
(com aspas simples); uso aspas duplas aqui porque estamos dentro de uma'mv …'
string entre aspas simples ( ).E talvez
vai funcionar.
Além disso, o que você tentou inicialmente pode funcionar se você definir
LANG
comode_DE.UTF-8
.A
de-ASCII
transliteração deuconv
fará o que você quiser. Por exemplo, com as versões pré-compostas e decompostas, bem como com versões maiúsculas e minúsculas doä
caractere:(observe também a
Ä
alteração paraAE
ouAe
dependendo do contexto).Então, aqui, você pode tentar converter todos os arquivos com caracteres não-ASCII em seus nomes com algo como (em zsh):
Exemplo:
Remova o
-n
(ensaio) se estiver satisfeito.Ou para evitar executar um
uconv
por arquivo caso você tenha milhões para renomear.Como resposta à sua pergunta mais genérica de como encontrar arquivos com caracteres com trema em sua forma decomposta, você só precisa procurar o caractere de trema combinado (U+308).
Então:
Ou se tiver que seguir apenas um dos AOUaou:
Para aqueles em seus formatos pré-compostos, você precisará listá-los todos individualmente:
Ou:
Usando a notação zsh
$'\uXXXX'
agora suportada por alguns outros shells, incluindo bash.