2つの異なるコマンドの結果を単一のコマンドにマージおよびパイプする方法は?


35

2つの異なるコマンドからのマージ(ユニオン)出力を望み、それらを単一のコマンドにパイプします。

愚かな例:

出力をマージするコマンド:

cat wordlist.txt
ls ~/folder/*

に:

wc -l

この例では、wordlist.txtに5行と3ファイルが含まれている場合、wc -l8を返します。

$cat wordlist.txt *[magical union thing]* ls ~/folder/* | wc -l
8

それ、どうやったら出来るの?

回答:


56

あなたの魔法の結合物はセミコロンです...そして中括弧:

    { cat wordlist.txt ; ls ~/folder/* ; } | wc -l

中括弧は、パイプ記号|が結合された出力に影響するように、コマンドをグループ化するだけです。

また()、コマンドグループをカッコで囲んで、サブシェルでコマンドを実行することもできます。これには、中括弧との微妙な違いがあります。たとえば、次のことを試してください。

    cd $HOME/Desktop ; (cd $HOME ; pwd) ; pwd
    cd $HOME/Desktop ; { cd $HOME ; pwd ; } ; pwd

現在の作業ディレクトリを含むすべての環境変数は、括弧グループを終了した後にリセットされますが、中括弧グループを終了した後ではないことがわかります。

セミコロンに関しては、選択肢には&&and ||記号が含まれます。これらは、最初のコマンドが成功した場合またはそうでない場合にのみ条件付きで2番目のコマンドを実行します。

    cd $HOME/project && make
    ls $HOME/project || echo "Directory not found."

1
うまくいきます!私が学ぶのを助けてください-ここで中括弧は正確に何をしていますか?他にどんな魔法の力がありますか?
デビッドオニール

@DavidOneill { list; }複合コマンドです。From bash(1)リストは現在のシェル環境で単に実行されます。リストは改行またはセミコロンで終了する必要があります。[..]戻りステータスはリストの終了ステータスです。
-Lekensteyn

回答にもう少し情報を追加しました。bashを使用したシェルスクリプトの決定的なガイドはbashのマンページでman bash、コマンドラインから入力して参照します。
パブロム

する必要があります; これらのコマンドでは、wordlist.txtファイルが存在しない場合は&&になりませんか?
リンツウィンド

場合wordlist.txtからエラーを存在しないcat標準エラー出力に表示されますが、標準出力に、そうではないwc -lことから、任意の行をカウントされません。~/folder存在しない場合も同様です。2> /dev/nullこれらの各コマンドとセミコロンの間に標準エラーのノイズを防ぐために追加することができますが、見苦しいだけでなく、エラーメッセージは行をカウントするためには無害です。
パブロム

8

以来wc、入力としてファイルパスを受け入れ、あなたはまた、プロセス置換を使用することができます。

wc -l <(cat wordlist.txt; ls ~/folder/*)

これはおおよそ次と同等です。

echo wordlist.txt > temp
ls ~/folder/* >> temp
wc -l temp

ls ~/folder/*サブディレクトリの内容があれば、それも返します(グロブ拡張のため)。の内容を一覧表示するだけの場合は~/folder、を使用しますls ~/folder


これwc -lは単なる例であり、実際には、このオプションを持たないより複雑なものにパイプしています。
デビッドオニール

2
@DavidOneillさて、catファイル引数を受け入れるので、を使用することcat <(cat wordlist.txt; ls wordlist.txt) | wc -lもできますcat wordlist.txt <(ls wordlist.txt) | wc -l。これはもちろん非常にいですが、コマンドラインツールの無限の可能性を示しています。
-Lekensteyn

1
@DavidOneill正解、今修正しました、ありがとう。
-Lekensteyn

1
あなたが欲しいls ~/folder/場合ほど~/folderであるシンボリックリンクがlsそのターゲットの内容の代わりに、リンク自体を示しています。ところで、すべてのlsコマンドの後には、-1行ごとに1つのファイルが出力され、wc -lファイルをカウントする有効な方法になるようにする必要があります。
パブロム

@pablommeあなたはシンボリックリンクについては真実ですが-1、出力はターミナルではなくパイプであるため、暗示されています。
-Lekensteyn

2

私は自分自身に同じ質問をしていましたが、結局短いスクリプトを書くことになりました。

magicalUnionThing(私はそれを呼び出しますappend):

#!/bin/sh
cat /dev/stdin
$*

そのスクリプトを実行可能にする

chmod +x ./magicalUnionThing

今やる

cat wordlist.txt |./magicalUnionThing ls ~/folder/* | wc -l

それが何をする:

  • 標準入力を標準出力に送信する
  • 引数を実行します。$*すべての引数を文字列として返します。そのコマンドの出力は、デフォルトでスクリプトの標準出力に送られます。

したがって、magicalUnionThingの標準出力は、その標準入力+引数として渡されるコマンドの標準出力になります。

他の回答によると、もちろんより簡単な方法があります。
たぶん、この代替案はいくつかのケースで役に立つかもしれません。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.