以下に基づいてファイルをインデックス(検索)するためのツールはありますか?メタデータ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/sh
shebangが偽のBourneシェルを指すホストでもPOSIX互換モードで実行した場合/usr/bin/sh --> /usr/bin/bash
。ラッパーで構成されています
find
。実装で一般的に見られるすべてのアドオンは実装されているわけではありませんが、find
OPの要件を満たし、検索の改善に興味がある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
上記では、setfattr
x user.__
attributeという名前の名前空間を指しますlikes
。新しいx属性は、KV(キーと値)のペアとして定義されます。ここで、キーは文字列であり、likes
その値はで始まる必要があります。dislikes
filebirth
-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