名前のリストを含むファイルがあります。
john
paul
ringo
george
...
その後、さまざまな名前の複数のファイルがあります。
maria.iso
jose.iso
pablo.iso
john.iso
jack.iso
jane.iso
...
find
ファイルリストの1つと同じ名前のファイルのみを出力するか、一致するものがない場合はファイルを出力しないコマンドを実行したいと思います。私の例では:
john
このような:
find . -type f -name "*.iso" (in array)
しかし、これが可能かどうか、それからどこから始めるべきかわかりません。
これまで私の唯一のアイデアはforループを書くことでしたが、これは醜くて非効率的に見えます。
ありがとう
答え1
readarray
名前を配列として読み取るために使用されますnames
。次に、配列の各要素を繰り返してコマンドを実行しますfind
。
readarray names < names.txt
for n in ${names[@]};do
find . -type f -name "${n}.iso"
done
答え2
find
以下で「または」テストを実行できますfind . -name a -o -name b ...
。
したがって、ファイルを変更してスイッチを追加し、xargs
build find コマンドを使用します。
awk 'NR > 1 {print "-o"}; {print "-name", $0".iso"}' input-file | xargs find .
十分に小さいリストの場合は1つだけ実行する必要がありますfind
。ファイル名にスペース、引用符、またはその他の特殊文字が含まれている場合は、ASCIIヌル文字で区切られたレコードの使用を検討してください(この場合はGNU sedを使用して入力を変更できます)。 。
答え3
次のコマンドを使用すると簡単になりますzsh
。
names=(${(f)"$(<name-list.txt)"})
ls -ld -- **/(${(~j[|])names}).iso(D)
どこ:
$(<file)
kshスタイル演算子、次に拡張可能file
f
パラメータ拡張は行の分割を表示するf
ため$names
name-list.txt
j[|]
:配列要素を連結するためにwithを使用します。|
~
|
リテラルではなくグローバル演算子(ここでは置き換えに使用されます)と考えてください|
。**/
:再帰ワイルドカード(すべてのレベルのサブディレクトリから検索)(D)
:glob修飾子dotglob
(隠しファイルを含め、隠しディレクトリ検索を含むfind
)はglobを有効にします。