xargsなしでstdinから取得したファイルを分類する方法

xargsなしでstdinから取得したファイルを分類する方法

私はシェルをよりよく学び、常にxargsに頼る必要がないようにするために他の方法を見つけようとしました。

find . -name *.tcl | xargs -I{} cat {}

xargsを使用すると混乱しているように感じ、これを達成するためのいくつかの方法があるかどうか疑問に思います。

編集:他の解決策は次のものを使用することです。

find . -name "*.tcl" | cat `cat /dev/stdin`

なぜファイル名を最初に分類してから、文字列の代わりにファイルに分類するのかわかりません。

答え1

子プロセスで find を使用し、出力を cat に供給することもできます。 :)

cat $(find . -name "*.tcl")

答え2

照会時にexecを使用できます。

find . -name "*.tcl" -exec cat {} \;

-execその間のすべてと末尾は\;実行するコマンドです。 xargsと同様に、検索結果を{}に置き換えることができます。見つかった各ファイルに対してcatが実行されます(xargsがSTDINを介して提供されたファイルのリストを繰り返す方法と似ています)。

一部の人々はパイプを使用しないか、他のアプリケーションを起動しないので、これはより効率的であると思うかもしれません。

答え3

を使用している場合は、bash次の操作を行います。

shopt -s globstar # to match files recursively
cat -- **/*.tcl

答え4

簡素化のために提案されたクリーンで読みやすいソリューションを好みます。マーク・コマリンスキー。しかし、Bashにはこれを行う方法がたくさんあります。もう一つの興味深いアプローチは、リダイレクトを完全に回避し、catリダイレクトを活用することです。

find . -name '*.tcl' -exec sh -c 'printf "%s\n" "$(< {})' \;;

実際に Bash 組み込み機能のみを使用してすべての操作を実行するには、次のようにリダイレクトを使用できます。混沌としたグローバルソリューション:

shopt_globstar_temp="$(shopt -p globstar)";
shopt -s globstar;
for filename in **/*.bat; do
    printf "%s" "$(< "${filename}")";
done;
${shopt_globstar_temp};

これらは少し複雑ですが、ここで私の目的はBashができることを示すことです。ファイル記述子とリダイレクトのいくつかの強力な機能。特定の問題に対して多くの解決策があることがよくあります。


なぜファイル名を最初に分類してから、文字列の代わりにファイルに分類するのかわかりません。

の出力はcat /dev/fd/stdin前の例と同じなので、対応するファイルのリストで効果的に置き換えfindられ、そのファイルのリストを引数のリストとして使用します。<filename1>.tcl <filename2>.tcl ...cat

同じ例でcatを使用する理由がわからない場合は、すべてのプログラムが引数を同じように処理するわけではstdinないからです。を介してstdinデータを転送すると、読み取るファイル名として解釈されるのではなく、同じデータが単に出力されます。catstdincat

関連情報