tr "\n" "\n"`を介してパイプするとき、 `ls`の出力が異なるように見えるのはなぜですか?

tr "\n" "\n"`を介してパイプするとき、 `ls`の出力が異なるように見えるのはなぜですか?

マニュアルページには次のようtr(1)に記載されています。

       tr - translate or delete characters

SYNOPSIS
       tr [OPTION]... SET1 [SET2]

DESCRIPTION
       Translate, squeeze, and/or delete characters from standard input, writing to standard output.

私が知っている限り、これは「\ n」を取り、「\ n」に置き換えることを意味します(つまり、何も変わらないことを意味します)。

しかし、これがなぜls | tr '\n' '\n'次のような効果をもたらすのか説明しません。

 $ ls 
 Documents   Downloads   Git   Music   Pictures  '#recycle'   Videos
2019-Dec-24 07:28:44 PM modernNeo:modernNeo-debian/home/modernNeo
 $ ls | tr "\n" "\n"
Documents
Downloads
Git
Music
Pictures
#recycle
Videos

答え1

このユーティリティの出力は、出力がls端末に直接書き込まれるのかパイプに書き込まれるのかによって異なります。

tr '\n' \n'次のコマンドを使用すると、同じ動作が発生しますcat

$ ls
file-00 file-01 file-02 file-03 file-04 file-05 file-06 file-07 file-08 file-09
$ ls | cat
file-00
file-01
file-02
file-03
file-04
file-05
file-06
file-07
file-08
file-09

lsこの行は、1行に1つのファイルを一覧表示し、以下に説明するデフォルト出力です。このユーティリティのPOSIX規格:

デフォルトの形式は、標準出力に1行に1つの項目をリストする必要があります。;端末またはオプションのいずれかを指定する-C場合-mを除きます。-x端末に出力する場合、フォーマットは実装によって定義されます。

#recycleまた、パイプを介して出力をフィルタリングすると、ファイル名の周りの一重引用符が「消える」ことがわかります。実際、これはファイル名の一部ではありませんでしたが、GNUが端末に出力したときにls名前をレンダリングすることにしました(名前に含まれる文字に基づいており、#「特殊」と見なされます)。出力が端末に到達すると、一重引用符で囲まれた名前と列の出力は、標準で許可される「実装定義形式」です。

ファイルにリダイレクトしてパイプを置き換える(またはそれをサポートするシェルでプロセスを置き換える)、ls出力形式は「デフォルト形式」に指定され、各ファイル名は改行で区切られます。

関連情報