bash変数でファイルリストをzcatに渡す方法は?

bash変数でファイルリストをzcatに渡す方法は?

zcat単一の出力ストリームをbashパイプラインに渡そうとします。wc -lこの例では、これをパイプラインとして使用します。

zcat -f /var/log/log.3.gz /var/log/log.2.gz /var/log/log.1.gz /var/log/log | wc -l

実際に返されるのは行数です。

paths="/var/log/log.3.gz /var/log/log.2.gz /var/log/log.1.gz /var/log/log"
zcat -f "${paths}" | wc -l

gzip: /var/log/log.3.gz /var/log/log.2.gz /var/log/log.1.gz /var/log/log.gz: そのファイルやディレクトリはありません。

パイプラインが中間ファイルなしで1回のパスしか作成できないように、これらすべてのファイルをstdoutにマージするにはどうすればよいですか?.gz変数に追加された完全な文字列結果を単一のパラメータであるかのように渡しました。

答え1

var=('first value' 'second value'...)リストはの構文を使用して割り当てられますbash

paths=(/var/log/log.3.gz /var/log/log.2.gz /var/log/log.1.gz /var/log/log)
zcat -f -- "${paths[@]}" | wc -l

ofには、ファイル名引数が渡されないと出力がまったく生成されず、標準入力が読み取られる空の$pathリストが含まれていますzcat -f -- "${paths[@]}"zcat -f --zcat

この問題を解決するには、次の操作を行います。

{ (( ${#paths[@]} == 0 )) || zcat -f -- "${paths[@]}"; } | wc -l

または:

zcat -f -- </dev/null "${paths[@]}" | wc -l

/var/log/log*ファイルを逆順にリンクするには、以下のzshシェルを使用することをお勧めしますbash

zcat -f /var/log/log*(nOn) | wc -l

(これはameのn数値order(O歴代文字を使用)ですn。)

一致するファイルがない場合、上記の回避策は必要ありません。

$ zcat -f /var/log/log*(nOn) | wc -l
zsh: no matches found: /var/log/log*(nOn)
0

答え2

引用符のない変数は、シェルにトークン化とファイル名の生成を実行させます。最初の効果だけが欲しいので、後者を無効にすることができます。

paths="/var/log/log.3.gz /var/log/log.2.gz /var/log/log.1.gz /var/log/log"
(
  set -f
  zcat -f $paths | wc -l   # variable is unquoted
)

設定がそのサブシェルの存続期間中にのみ有効であるように括弧を追加しました。

明らかに、シェルをトークン化できるようにすることは、パス名にスペースが含まれているとシェルが破損することを意味します。

関連情報