(GNU)findはアクセントを区別しない(発音記号を区別しない)検索を実行できますか?

(GNU)findはアクセントを区別しない(発音記号を区別しない)検索を実行できますか?

ディレクトリ階層でファイルのアクセントを区別せずに検索を実行したいと思います。

$ touch a ą ä à á â
$ find . -iname '*a*'
./a
# How do I get find to return all 6 filenames?

私はDebian 11、Bullseyeを実行しています。

私のもの校正者非常に弱い!

アクセントを区別しない方法でルックアップを機能させるオプション、ロケール、またはその他の方法はありますか?

コメントで要求されたとおり、locale次を返します。

LANG=en_GB.UTF-8
LANGUAGE=en_GB:en
LC_CTYPE="en_GB.UTF-8"
LC_NUMERIC="en_GB.UTF-8"
LC_TIME="en_GB.UTF-8"
LC_COLLATE="en_GB.UTF-8"
LC_MONETARY="en_GB.UTF-8"
LC_MESSAGES="en_GB.UTF-8"
LC_PAPER="en_GB.UTF-8"
LC_NAME="en_GB.UTF-8"
LC_ADDRESS="en_GB.UTF-8"
LC_TELEPHONE="en_GB.UTF-8"
LC_MEASUREMENT="en_GB.UTF-8"
LC_IDENTIFICATION="en_GB.UTF-8"
LC_ALL=

答え1

TL;DRの最後までスクロール

これは良い質問です。質問ありがとうございます。

私が知っている限り、アクセントを区別しない検索を実行することは可能ですが、デフォルトではなく、自動的に実行されるわけでもありません。次のコマンドを使用して、6つのサンプルファイルをすべて見つけることができます。

find . -name '[[=a=]]'

これは、類似しているがアクセントを持つすべての文字を表すために使用される標準のPOSIX glob表記です。

したがって、アクセントバージョンがある可能性があるすべての文字を知っている場合は、上記の表記法を使用できます。明らかにあなたの検索から。たとえば、

find . -name 'fran[[=c=]]ais' # To match a cedilla

しかし、それは退屈で非常に不満足です。

この[[=a=]]表記法は、アクセントバージョンのない文字にも使用できます。だから[[=k=]]一致しますk

だから私はスクリプトを作成することを提案します(アクセント付き)はコマンドラインから文字列を取得し、[[=x=]]各文字を対応するバージョンに置き換え、結果を印刷してから次のように組み合わせることができます。探す。たとえば、

#!/usr/bin/env perl
print join('', map { /\p{Letter}/ ? "[[=$_=]]" : $_ } split //, $ARGV[0]), "\n";

一緒に使う探す次のように見えます。

find . -name "`accented a`"

自動的に感じたいと思っていて、ただ使うなら探す最も簡単な方法でシェルスクリプト(ファインダー)結合探すそしてアクセント付き:

#!/bin/sh
find "$1" -name "`accented \"$2\"`"

これにより、次のことができます。

ffind . a

しかし、これを行うと使用できなくなります。探す他の述語。

必要なときは実物を使うべきです。探すそしてアクセント付き明示的に(上記のように)。

ここ

よりスマートな解決策はラッパーです探すファインダー-name-inameパラメータをスキャンして効果的に適用します。アクセント付き次のパラメータに追加した後、変更された結果を実行します。探す注文する。たとえば、

#!/usr/bin/env perl
use warnings;
use strict;
# ffind - find wrapper that makes -name and -iname accent-insensitive
my @cmd;
while (@ARGV)
{
    # Gather command line arguments
    push @cmd, shift @ARGV;

    # Make -name and -iname arguments accent-insensitive
    if ($cmd[-1] =~ /^-i?name$/ && @ARGV)
    {
        push @cmd, join('', map { /\p{Letter}/ ? "[[=$_=]]" : $_ } split //, shift @ARGV);
    }
}
exec 'find', @cmd;

その後、これを実行して6つのサンプルファイルをすべて見つけることができます。

ffind . -name a

もちろん電話も可能です。探す'find'最後の行を に変更すると'/usr/bin/find'こうなります。探す透明にアクセントを区別しない:

find . -name a

残念ながら、この完全な方法はDebian 12などの一部のシステムでのみ機能しますが、すべてではありません。 :-(

答え2

名前を分解形式に変換して結合マークを削除したら、次のことを確認できます。

find . -print0 |
  perl -C -MUnicode::Normalize -MFile::Basename -0 -lne '
    $name = NFD(basename($_)) =~ s/\pM//r;
    print if $name =~ /a/' |
  xargs -r0 ls -ld --

関連情報