web-dev-qa-db-ja.com

`sort <(ls -l)`は機能するが、 `sort <(ls -l)`は失敗するのはなぜですか?

今日、私はこの記事でfifoについて何かを学んでいます: cat <(ls -l)に言及する名前付きパイプの紹介

エラーを表示するsort < (ls -l)を使用していくつかの実験を行いました。

-bash: syntax error near unexpected token `('`

その後、コマンドに余分なスペースを誤って追加したことがわかりました。

しかし、なぜこの余分なコマンドがこの失敗につながるのでしょうか?リダイレクトシンボルを(の近くに配置する必要があるのはなぜですか?

32
Zen

これは_<_ではないため、完全に異なる<()です。これは プロセス置換 と呼ばれ、あるプロセスの出力を別のプロセスの入力として使用できるようにする特定のシェルの機能です。

_>_および_<_演算子は、filesへの入力および(== --- ==)ファイルからの入力をリダイレクトします。 <()演算子は、ファイルではなくコマンド(プロセス)を扱います。あなたが走るとき

_sort < (ls)
_

コマンドlsをサブシェルで実行しようとしています(かっこはその意味です)、そのサブシェルを入力ファイルとしてsortに渡そうとしています。ただし、これは受け入れられない構文であり、見たエラーが発生します。

45
terdon

それが意図されている方法だからです。

bash<(...)は、プロセス置換の構文です。 kshの同じ演算子からコピーされます。

_<_、_(_、_)_、_|_、_&_、_;_はbashの特別な字句トークンで、特殊な演算子をさまざまな組み合わせで形成します。 _<_、_<(_、_<<_、_<&_...それぞれに役割があります。 _<_はリダイレクト用です。 _<file_、_< file_は、ファイルから入力をリダイレクトします。 <'(file)'は、_(file)_というファイルから入力をリダイレクトしますが、<(file)は、リダイレクト演算子ではない別の演算子です。

< (file)は_<_の後に_(file)_が続きます。そのコンテキストでは、bashでは、_(file)_は無効です。 _(...)_は、次のような一部のコンテキストでは単一のトークンとして有効です。

_(sub Shell)
func () {
  ...
}
var=(foo bar)
_

しかしではない

_sort < (cmd)
_

fishシェルでは異なります。 fishでは、_(...)_はコマンド置換用です(bash$(...)に相当)。また、_<_は、Bourneのようなシェルのような入力リダイレクト用です。

したがって、fishには:

_sort <(echo file)
_

次と同じになります:

_sort < (echo file)
_

あれは:

_sort < file
_

しかし、それはbashのプロセス置換とはまったく異なるものです。

yashシェル、別のPOSIXシェルでは、<(...)プロセス置換ではなく、プロセスリダイレクトです。

そこで、

_sort <(ls -l)
_

の略:

_sort 0<(ls -l)
_

リダイレクト演算子です。それは多かれ少なかれ同等です:

_ls -l | sort
_

bashでは、<(ls -l)はパイプのパスに展開されるため、次のようになります。

_ls -l | sort /dev/fd/0
_

zshでは、_(...)_がグロブ演算子(_(*.txt|*.png)_はtxtおよびpngファイルに展開されます)として、およびグロブ修飾子(*(/)は、たとえばディレクトリファイルに展開されます)。

zsh内:

_sort < (ls -l)
_

その_(ls -l)_はグロブ修飾子として扱われます。 l glob修飾子はリンクの数で一致し、lの後に数字を期待します(ls -ld ./*(l2)は2つのリンクを持つファイルを一覧表示します)。そのため、そこで_zsh: number expected_エラーが発生します。

_(w)_が空の名前の書き込み可能なファイルと一致するため、sort < (w)は代わりにzsh: no matches found: (w)エラーを返します。

sort < (w|cat)は、現在のディレクトリにあるwおよびcatファイルの内容をソートします...

22