結合されたUnicode文字の検索と置換

結合されたUnicode文字の検索と置換

äディレクトリ名とファイル名にいくつかの「特殊」文字(、、、öüが含まれているDebianシステムには深いフォルダ構造があります。ただし、これは「ISO-8859-1」ではなく、Unicode結合文字の形です。私が知っている限り、a 2つの点(分音符/ウムラウト)を「別の」文字として追加するのは簡単な問題です。

findと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")"' _ {} \;

ただし、引数のパラメータがISO-8859-1の代わりにUnicodeに結合されている場合、ファイル/フォルダ名に表示さfindれるすべての項目も選択されているようです。例えば、aä-nameä

$ find . -name "*[ä]*"  //<-- one letter ä
./filename_one_letter_ä
$ find . -name "*[ä]*"  //<-- combining letter ä
./filename_with_just_a
./filename_one_letter_ä
./filename_with_combining_diaeresis_ä

したがって、  sedファイル名を変更せずに渡すので、たとえば、""から""にmv名前を変更するように要求するときに文句を言います(つまり、ソースとターゲットは同じです)。BaustandBaustand

findを使用して検索できない場合、Linuxシステムのファイル/フォルダ構造内でUnicode、、、、、のすべての組み合わせäを検索して置き換える方法は?試してみる別の方法はありますか?öüÄÖÜ

私のファイルとディレクトリ名の例は次のとおりです。

/Projekte/03-11_Törggel_Mammern/Baustand/03-11_Törggel-Baustand_190501_0009.jpg

名前を次に変更したいです。

/Projekte/03-11_Toerggel_Mammern/Baustand/03-11_Toerggel-Baustand_190501_0009.jpg

出力echo $LANGはですen_US.UTF-8

答え1

このATMを再現(またはテスト)することはできませんが...

まあ、あなたは[xyz]一致を知っています。x または y または z。私の考えでは、(結合文字を使用して)言うとき、[äöü…]それは見ていると思います。

  • a
  • (結合する) ¨
  • o
  • (結合する) ¨
  • u
  • (結合する) ¨

aしたがって、名前に、、oを含むファイルを探します。u または(組合せ)  ¨、必ずしもそうではないがまたは 

したがって、別々に参照してください。

find . -depth -name "*ä*" -exec bash -c 'mv "$1" "$(echo "$1" | sed -e "s/ä/ae/g")"' _ {} ';'
find . -depth -name "*ö*" -exec bash -c 'mv "$1" "$(echo "$1" | sed -e "s/ö/oe/g")"' _ {} ';'
find . -depth -name "*ü*" -exec bash -c 'mv "$1" "$(echo "$1" | sed -e "s/ü/ue/g")"' _ {} ';'
find . -depth -name "*Ä*" -exec bash -c 'mv "$1" "$(echo "$1" | sed -e "s/Ä/Ae/g")"' _ {} ';'
find . -depth -name "*Ö*" -exec bash -c 'mv "$1" "$(echo "$1" | sed -e "s/Ö/Oe/g")"' _ {} ';'
find . -depth -name "*Ü*" -exec bash -c 'mv "$1" "$(echo "$1" | sed -e "s/Ü/Ue/g")"' _ {} ';'

(角かっこを除く)。一部のファイル名では(引用符を除く)がecho $1失敗する可能性があります。 (';'同等\;。スタイル上のバックスラッシュを避けることをお勧めします。)

またはあなたが本物本物1 つのコマンドですべての操作を実行するには、次のようにします。

find . -depth "(" -name "*ä*" -o -name "*ö*" -o -name "*ü*"     \
               -o -name "*Ä*" -o -name "*Ö*" -o -name "*Ü*" ")" \
       -exec bash -c 'mv "$1" "$(printf "%s" "$1" | sed -e "s/ä/ae/g; s/ö/oe/g; s/ü/ue/g; s/Ä/Ae/g; s/Ö/Oe/g; s/Ü/Ue/g")"' _ {} ';'

printf "%s"機能的には非常に似ていますechoが、より安全です。スタイル的には通常(二重引用符を含む)を使用します。ここでは、単一引用符()文字列内にあるprintf '%s'ため、二重引用符を使用します。)'mv …'

可能

… "(" -iname "*ä*" -o -iname "*ö*" -o -iname "*ü*" ")" …

動作します。


LANGまた、最初に試したジョブをに設定すると機能することがありますde_DE.UTF-8

答え2

これde-ASCII音域uconvあなたがしたいことをします。たとえば、事前設定および分解された文字と大文字と小文字のバージョンは次のとおりですä

$ printf '\u00c4 \u00e4 A\u0308 a\u0308\n'
Ä ä Ä ä
$ printf '\u00c4\u00e4A\u0308a\u0308' | uconv -x name
\N{LATIN CAPITAL LETTER A WITH DIAERESIS}\N{LATIN SMALL LETTER A WITH DIAERESIS}\N{LATIN CAPITAL LETTER A}\N{COMBINING DIAERESIS}\N{LATIN SMALL LETTER A}\N{COMBINING DIAERESIS}
$ printf '\u00c4\u00e4A\u0308a\u0308 \u00c4 A\u0308 \u00c4B\n' | uconv -x de-ASCII
AeaeAeae AE AE AEB

(また、状況によっては「またはÄ」に変更されることに注意してください)。AEAe

したがって、ここで次のようなものを使用して、名前にASCII以外の文字を含むすべてのファイルを変換することができます(zshから)。

autoload zmv
zmv -n $'(**/)(*[^\1-\177]*)' '$1$(print -rn -- $2 | uconv -x de-ASCII)'

例:

$ touch $'\u00c4\u00e4A\u0308a\u0308'
$ touch $'St\ue9phane' $'Ste\u301phane'
$ zmv -n $'(**/)(*[^\1-\177]*)' '$1$(print -rn -- $2 | uconv -x de-ASCII)'
mv -- ÄäÄä AeaeAeae
mv -- Stéphane Stephane
mv -- Stéphane Stephane

満足すれば削除-n(テスト実行)します。

または、uconv名前を変更する必要があるファイルが何百万ものある場合に備えて、ファイルごとに1つずつ実行しないでください。

files=(**/*[^$'\1-\177']*)
typeset -U basenames=($files:t)
typeset -A translation
print -rNC1 -- $basenames | uconv -x de-ASCII |
  for name in $basenames; do
    IFS= read -rd '' translated && translation[$name]=$translated
  done

zmv -n $'(**/)(*[^\1-\177]*)' '$1${translation[$2]-$2}'

分解された形式の分音文字を含むファイルを検索する方法について、より一般的な質問に対する答えとして結合された分音文字(U + 308)を見つけるだけです。

だから:

find . -name $'*\u0308*'

または、AOUaouの1つだけに従う必要がある場合:

find . -name $'*[AOUaou]\u0308*'

事前結合形式の場合は、別々にリストする必要があります。

find . -name '*[ÄËÏÖÜäëïöüÿŸǕǖǗǘǙǚǛǜǞǟȪȫ΅ΐΪΫΰϊϋϔӒӓӚӛӜӝӞӟӤӥӦӧӪӫӬӭӰӱӴӵӸӹḦḧḮḯṎṏṲṳṺṻẄẅẌẍẗ⍡⍢⍣⍤⍥⍨⍩⸚]*'

または:

find . -name $'*[\uA8\uC4\uCB\uCF\uD6\uDC\uE4\uEB\uEF\uF6\uFC\uFF\u178\u1D5\u1D6\u1D7\u1D8\u1D9\u1DA\u1DB\u1DC\u1DE\u1DF\u22A\u22B\u385\u390\u3AA\u3AB\u3B0\u3CA\u3CB\u3D4\u4D2\u4D3\u4DA\u4DB\u4DC\u4DD\u4DE\u4DF\u4E4\u4E5\u4E6\u4E7\u4EA\u4EB\u4EC\u4ED\u4F0\u4F1\u4F4\u4F5\u4F8\u4F9\u1E26\u1E27\u1E2E\u1E2F\u1E4E\u1E4F\u1E72\u1E73\u1E7A\u1E7B\u1E84\u1E85\u1E8C\u1E8D\u1E97\u2361\u2362\u2363\u2364\u2365\u2368\u2369\u2E1A]*'

$'\uXXXX'bashを含むいくつかの他のシェルは、zshを使用した表記をサポートしています。

関連情報