フォルダに対してトレースを実行しようとしていますが、ファイルにfind -nameフィルタを使用したいと思います。そのため、フィルタを含むfilter_filesというファイルを用意しました。たとえば、次のようになります。
cat filter_files:
-name "a.txt" -o -name "b.txt"
findコマンドを実行して上記のフィルタを追加してみましたが、何も返しません。ファイルの内容を作成して find コマンドに貼り付けると成功します。
私のbashファイルの関連行は次のとおりです。
local filter=$(cat $filter_files)
find_files=$(find "$path" -type f \( $filter \) )
私が望むことができるかどうか説明しますか?では、どのように動作させることができますか?
答え1
ファイルに以下が含まれている場合
-name "a.txt" -o -name "b.txt"
あなたは走る
find "$path" -type f \( $(cat file) \)
その後、シェルはcat
単語分割を介して出力を実行し、パラメータ、、、、および引用符-name
を生成します。ここで引用符は実際にはパラメータの一部です。 (引用符もスペースを保護しません。このような入力文字列は2つのフィールドとを生成します。分割結果はファイル名/ワイルドカードで生成されるため、この時点ではパスの代わりに拡張されます。そのまま)。"a.txt"
-o
-name
"b.txt"
"foo bar"
"foo
bar"
foo*.txt
find
単語分割が非常に簡単だからです。ただ実際にスペースに分割いいえ実行出力は、シェル構文全体を通して解析されます。 (そうであれば、コマンド置換を含むすべての拡張が常に再帰的に実行されるという意味なので、非常に危険です。任意のデータを比較的安全に処理するためにシェルを使用することは不可能です。)
ファイルの1つのセクションを完全に構文的に処理するには、runコマンドを使用する必要がありますeval
。たとえば、次のようになります。
eval 'find "$path" -type f \( '"$(cat file)"' \)'
ここでは、シェルが引用符とコマンドの置換を処理した後、eval
次の文字列を取得します。この文字列は、引用符の処理やすべての拡張を含むシェルコマンドで処理されます。
find "$path" -type f \( -name "a.txt" -o -name "b.txt" \)
(ただし、ファイルにegが含まれている場合はコマンドが実行されます。ただし、二重処理を避けるために内部シェル拡張"$(reboot)"
に任せます。)"$path"
たとえば、ファイルの単語を配列に割り当ててeval
から、最後のコマンドでその配列を使用するなど、いくつかの手順で上記の操作を実行できます。アイデアと考慮事項は同じです。
ファイル形式を再検討することもできます。たとえば、各引数を別々の行に配置して引用符をオフにすると、解析が簡単になります。
たとえば、ファイルが次のような場合:
-name
a.txt
-o
-name
foo bar.txt
readarray
各入力行を別々の配列要素として読み取って同様の操作を実行できます。
#!/bin/bash
readarray -t args < file
find "$path" -type f \( "${args[@]}" \)
(改行文字を含むファイル名を処理できないという点では依然として制限されていますが、この場合はおそらくまれで、他の問題を引き起こす可能性があります。)
次に、必要なものが-name
一致するものであれば、ファイルにパターンをリストし、-o -name
プログラムで定型句を生成することができます。
また見なさい:
- https://mywiki.wooledge.org/WordSplitting
- 変数に保存されたコマンドをどのように実行できますか?(関連する質問とアレイコマンドラインの構築の一般的な例が含まれています)
- 引数で find コマンドを書く
find
(ビルドコマンドラインのより具体的な例が含まれています)
答え2
使用:
-o
簡単にするには、行を分割してファイルから削除する必要があります。
find "$path" -type f $(sed '1q;d' filter_files) -o $(sed '2q;d' filter_files)
または:
単一の文字列。
filter_conditions=$(<sed '1q;d' filter_files)
find_files=$(find "$path" -type f \( $filter_conditions \))