インデックスファイルメタデータ

インデックスファイルメタデータ

以下に基づいてファイルをインデックス(検索)するためのツールはありますか?メタデータLinuxでは?検索して見つけました(ここ)Linuxでファイルインデックスを作成するためのいくつかのツールがあります。

ただし、これらのインデックスファイルにはメタデータがないようです(またはドキュメントでメソッドが見つからない可能性があります)。これ答えのように見えるかもしれませんが、文書が短いので、これが実際に私が探しているものかどうかはわかりません。

私はこれを見つけました:Gワークスペース、これはあまり正当ではありませんが、メタデータベースのインデックス作成を許可することが示されています。

GWMetadataは、アクティブフォルダ機能を含むメタデータインデックスと検索システムです。

私の目標

より正確には、macOで(デフォルトで)できることを模倣したいと思います。

# Create a file and set metadata
touch test_file.txt
xattr -w com.apple.metadata:MY_META todo test_file.txt
# Wait a few seconds for the index to update
sleep 5
# Search files that have a given metadata
mdfind "MY_META=todo"

作成したばかりのファイルのパスを返します。$(pwd)/test_file.txtこのコマンドを自動化する必要があるため、CLIインターフェイスを備えたツールを探しています。

ベストアンサー1

私はLinux(Debianバージョン)またはBSDホストに同様の機能があることに気づいていませんが、xattrアクティブなシステムでは直接実装するのはそれほど複雑ではありません。私はあなたに可能な解決策を提供しますこの回答の最後にPOSIX互換スクリプト形式探す(いいえ索引それ自体)。 CLI を使用するヘルプ機能を組み込んだので、使用段階に達するためにコードのすべての詳細を詳しく見る必要はありませんが、全体的には「コードの読み取り」が最善のアドバイスです。

インデックスは変更されずにスクリプトを実行する必要がありますが、デーモン(おそらくsystemdサービス単位)で実行し、小規模データベースを更新する必要があります(ある種のテーブルに関連データを格納することを意味します)。ただし、この作業を続行すると、KDEのBalooの場合と同様に、インデックス付きFSホストに大きな負担がかかる可能性があります。そうするべき説得力のある理由がない場合は、私はそれを完全に避け、ここで提案されているようなより軽いCLIポイント検索ユーティリティに固執します。


スクリプトの説明:findxattr

  • よく知られているfind外部ユーティリティとその慣用語に基づいています。
    find [options, filters ...] -exec sh -c '[...]' sh_exec "{}" \; 2> dev/null

  • #!/usr/bin/shshebangが偽のBourneシェルを指すホストでもPOSIX互換モードで実行した場合
    /usr/bin/sh --> /usr/bin/bash

  • ラッパーで構成されていますfind。実装で一般的に見られるすべてのアドオンは実装されているわけではありませんが、findOPの要件を満たし、検索の改善に興味があるClIユーザーに柔軟性を提供します。具体的には、以下を実装します。

    • を発行してfindxattr -h|--help正しい使い方を文書化する「ヘルプ」モード、
    • 長いオプションと短いオプションの前には、それぞれハイフン1つと2つがあります。
    • 2つのフィルタ-p|--path-m|--md|--maxdepth、非常に似ています
      find [-maxdepth <d>] [-path <path_specs>] ...(参照man find
    • グローバル検索$PWD(引数なしで呼び出すか、を使用して呼び出す場合-a|--all)、
    • x 属性の KV 属性で検索を表示します。例:
      • キー -x|--xattr <xattr_name>==
      • -x|--xattr ==<xattr_value>
      • 両方 -x|--xattr <xattr_name>==<xattr_value>

    完全に引用されている場合、x属性の名前と値にスペースを含めることができます。

  • getopt簡単に解析できるオプションとスイッチ(スクリプト内)を含めるように簡単に拡張できます。追加のオプションとフィルタを利用するにはロジックを拡張する必要があります。既存のオプションを処理する方法は、ツールの範囲を拡張するための青写真と同じです。


スクリプトテスト
まず、おもちゃxプロパティを構築してください。

$ touch ~/fully/qualified/foo ~/fully/qualified/_1_path/bar ~/fully/qualified/_2_path/foobar ~/fully/qualified/baz

$ setfattr -n user.likes -v 'I like strawberries.' ~/fully/qualified/foo

上記では、setfattrx user.__attributeという名前の名前空間を指しますlikes。新しいx属性は、KV(キーと値)のペアとして定義されます。ここで、キーは文字列であり、likesその値はで始まる必要があります。dislikesfilebirth-v

デフォルトでは、x属性は常にattr次のようにユーザーの名前空間に作成されますsetfattr-vおよびで置き換えられます)。-V

$ cd ~/fully/qualified
$ attr -s dislikes -V 'hacks' ./foo
$ attr -s filebirth -V '20220627-193029-CEST' ./_1_path/bar
$ attr -s filebirth -V '20210330-185430-CEST' ./_2_path/foobar
$ attr -s dislikes -V 'java' ./baz

到着置く得る削除するまたはリスト互換性のあるファイルシステムオブジェクトでも使用できる拡張属性attr(参照man attr):

使用法:
attr [-LRSq] -s attrname [-V attrvalue] pathname # 値の設定
attr [-LRSq] -g attrname pathname # 値の取得
attr [-LRSq] -r attrname pathname # attr 削除 attr
[-LRq ] ] -l パス名 # 属性リスト
-s は stdin から値を読み込み、-g は stdout に値を書き込みます。

たとえば、次のようになります。

$ cd ~/fully/qualified

$ attr -qg likes ./foo
I like strawberries.
$ attr -qg filebirth ./_1_path/bar
20220627-193029-CEST

スクリプトは、次のようにタブ区切りの出力を生成します。

$ cd ~; pwd
/home/USER

$ findxattr -m 4                             # search entire subtree (from `$PWD`) with max depth of 4    
./fully/qualified/foo        likes        I like strawberries.
./fully/qualified/foo        dislikes     hacks
./fully/qualified/_1_path/bar        filebirth        20220627-193029-CEST
./fully/qualified/_2_path/foobar        filebirth        20210330-185430-CEST
./fully/qualified/baz        dislikes     java

$ findxattr -m 3 -x dislikes==               # search entire subtree (from `$PWD`) by name, depth
./fully/qualified/foo        dislikes     hacks
./fully/qualified/baz        dislikes     java

$ findxattr -m 4 -p "*lified/_2_*" -x filebirth== # search by depth, path, name
./fully/qualified/_2_path/foobar        filebirth        20210330-185430-CEST

$ findxattr -m 4 -x =='20220627-193029-CEST' # search entire subtree (from `$PWD`) by value, depth
./fully/qualified/_1_path/bar        filebirth        20220627-193029-CEST

$ findxattr -x filebirth==                   # search entire subtree (from `$PWD`) by name
./fully/qualified/_1_path/bar        filebirth        20220627-193029-CEST
./fully/qualified/_2_path/foobar     filebirth        20210330-185430-CEST

パスワード:

#!/usr/bin/sh

#-------------------------------------------------------------
# Author: CBhihe
# Copyright (c) 2022 C. K. Bhihe
# Available under GPL3 at github.com/Cbhihe
#-------------------------------------------------------------

version='0.5.0'

set -o posix
#set -x

getopt_parsed=$(getopt -q -s sh -a -l 'all,help,path:,xattr:,maxdepth:' -o '+ham:p:x:' -- "$@")
exit_code=$?
if [ $exit_code -ne 0 ]; then
    printf "getopt exited with code %d (%s).\n%s\n" $exit_code "getopt parsing error"\
    "The most probable cause is an unknown option. Review command usage with \`findxattr -h|--help'" >&2
    exit 1
fi

eval set -- "$getopt_parsed"
unset getopt_parsed

xattrkey=""
xattrval=""

while true; do
    case "$1" in
        '-a'|'--all')
            /usr/bin/find . -exec sh -c '
                while IFS= read -r xattrkey; do
                    xattrvalout=`/usr/bin/attr -qg "$xattrkey" "$1" 2>/dev/null`
                    printf "%-20s\t%-20s\t%s\n" "$1" "$xattrkey" "$xattrvalout"
                done < <(/usr/bin/attr -ql "$1" 2>/dev/null)
            ' sh_exec "{}" \; 2>/dev/null
            exit 0
        ;;

        '-m'|'--maxdepth'|'--md'|'--maxd')
            tmp=`expr "$2" + 0`
            if (( "$2" == "$tmp" )); then
                maxdepth="$2"
                shift 2
                continue
            else
                printf "The script exited because '--maxdepth' arg must be a positive integer; current arg is %s.\n%s\n" "$2" "Review command usage with \`findxattr -h|--help'" >&2
                exit 1
            fi
        ;;

        '-p'|'--path')
            locpath="$2"
            #if [ "$locpath" = "\(/*[^/]\+\)\+/$" ]; then
            #if expr "$locpath" : "^\(/*\([^/]\)\+\)\+$" >/dev/null; then
            if expr "$locpath" : "^\(/*[^/]\+\)\+$" >/dev/null; then
                shift 2
                continue
            else
                printf "The script exited because '--path' arg must be a valid path; current arg is %s.\n%s\n" "$2" "Review command usage with \`findxattr -h|--help'" >&2
                exit 1
            fi
        ;;

        '-x'|'--xattr')
            keyval="$2"
            found=1
            if [ "$keyval" != "${keyval%==*}" ]; then
                found=0
            fi

            if [ "$found" = "1" ]; then
                printf "The script exited because '-x|--xattr' arg appears to be either empty or malformed.\nReview command usage with \`findxattr -h|--help'. Remember that extended attributes\ncan be sought by key AND value (<key>==<value>), or only by key (<key>==), or only by value\n(==<value>), where in each case the parenthesized content represents the '-x' option's argument.\n" >&2
                exit 1
            else
                xattrkey="${keyval%==*}"
                xattrval="${keyval#*==}"
                shift 2
                continue
            fi
        ;;

        '-h'|'--help')
            printf "%s\n" " " "This is a script based on \`find' but restricted to the options shown below. Both short- and long-" \
"format options are allowed. Unknown options cause the script to abort with exit code 1." \
" " \
"Usage:" \
"   \`findattr -h|--help' Prints this usage information. This option is used alone." \
"   \`findattr -a|--all'  Searches recursively for all files with xattr(s) starting at \$PWD." \
"                        This option is used alone." \
"   \`findattr [-m|maxdepth <d>] [-p|path <path>] [-x|xattr <xattr_name>==<xattr_value>]'" \
"       Options that can be combined:" \
"         -m|--maxdepth  Identical to \`find -maxdepth <d>' option, where \`d' a positive integer;" \
"                        Limits any recursive search with \`find', to the specified level of the file tree." \
"                        Note that the level of the file tree is understood counting from \$PWD, NOT" \
"                        from a supposed start point represented by the \`--path' argument if present." \
"         -p|--path      Identical to \`find -path <spath>' option;" \
"                        Traverse the file tree from the specified path, searching for ANY xattr," \
"                        unless the \`--xattr' option is invoked to filter the search so a specific xattr" \
"                        name and value can be sought." \
"         -x|--xattr     Lists files with specified \`xattr', n the file tree starting at \$PWD unless" \
"                        \`--path' is invoked." \
"                        A compulsory argument of the form: '<xattr_name>==<xattr_value>' is expected." \
"                        Quoting is needed in case the argument contains space(s) or special characters." \
" "
            exit 0
        ;;

        '--')
            shift
            break
        ;;

        *)
            printf "%s\n" "Internal error. Abort." >&2
            exit 1
        ;;

    esac
done

if [ -n "$maxdepth"  ] && [ -n "$locpath" ]; then
    set -- -maxdepth "$maxdepth" -path "$locpath"
elif [ -z "$maxdepth"  ] && [ -n "$locpath" ]; then
    set -- -path "$locpath"
elif [ -z "$maxdepth"  ] && [ -z "$locpath" ]; then
    set --
else
    #[ -n "$maxdepth"  ] && [ -z "$locpath" ]
    set -- -maxdepth "$maxdepth"
fi

if [ -n "$xattrkey" ] && [ -n "$xattrval" ]; then
#if expr "$xattrkey" != "" >/dev/null && expr "$xattrval" != "" >/dev/null; then
    xattrkey="$xattrkey" xattrval="$xattrval" /usr/bin/find . "$@" -exec sh -c '
        xattrvalout=`/usr/bin/attr -qg "$xattrkey" "$1" 2>/dev/null`
        if [ "$xattrvalout" = "$xattrval" ]; then
        #if expr "$xattrvalout" = "$xattrval" >/dev/null; then
            printf "%-20s\t%-20s\t%s\n" "$1" "$xattrkey" "$xattrvalout"
        fi
    ' sh_exec "{}" \; 2>/dev/null

elif [ -n "$xattrkey" ] && [ -z "$xattrval" ]; then
#elif expr "$xattrkey" != "" >/dev/null && expr "$xattrval" = "" >/dev/null; then
    xattrkey="$xattrkey" xattrval="$xattrval" /usr/bin/find . "$@" -exec sh -c '
        xattrvalout=`/usr/bin/attr -qg "$xattrkey" "$1" 2>/dev/null`
        if [ -n "$xattrvalout" ]; then
            while IFS= read -r xattrvalout || [ -n "$xattrvalout" ]; do
                printf "%-20s\t%-20s\t%s\n" "$1" "$xattrkey" "$xattrvalout"
            done <<<"$xattrvalout"
        fi
    ' sh_exec "{}" \; 2>/dev/null

elif [ -z "$xattrkey" ] && [ -z "$xattrval" ]; then
#elif expr "$xattrkey" = "" >/dev/null && expr "$xattrval" = "" >/dev/null; then
    /usr/bin/find . "$@" -exec sh -c '
        xattrkeys=`/usr/bin/attr -ql "$1" 2>/dev/null`
        if [ -n "$xattrkeys" ]; then
            while IFS= read -r xattrkey || [ -n "$xattrkey" ]; do
                xattrvalouts=`/usr/bin/attr -qg "$xattrkey" "$1" 2>/dev/null`
                if [ -n "$xattrvalouts" ]; then
                    while IFS= read -r xattrvalout || [ -n "$xattrvalout" ]; do
                        printf "%-20s\t%-20s\t%s\n" "$1" "$xattrkey" "$xattrvalout"
                    done <<<"$xattrvalouts"
                fi
            done <<<"$xattrkeys"
        fi
    ' sh_exec "{}" \; 2>/dev/null

else
    # [ -z "$xattrkey" ] && [ -n "$xattrval" ]; then
    # expr "$xattrkey" = "" >/dev/null && expr "$xattrval" != "" >/dev/null
    xattrkey="$xattrkey" xattrval="$xattrval" /usr/bin/find . "$@" -exec sh -c '
        xattrkeys=`/usr/bin/attr -ql "$1" 2>/dev/null`
        if [ -n "$xattrkeys" ]; then
            while IFS= read -r xattrkey || [ -n "$xattrkey" ]; do
                xattrvalouts=`/usr/bin/attr -qg "$xattrkey" "$1" 2>/dev/null`
                if [ -n "$xattrvalouts" ]; then
                    while IFS= read -r xattrvalout || [ -n "$xattrvalout" ]; do
                        if [ "$xattrvalout" = "$xattrval" ]; then
                            printf "%-20s\t%-20s\t%s\n" "$1" "$xattrkey" "$xattrvalout"
                        fi
                    done <<<"$xattrvalouts"
                fi
            done <<<"$xattrkeys"
        fi
    ' sh_exec "{}" \; 2>/dev/null

fi

exit 0

おすすめ記事