「ls|wc -l」が現在のディレクトリの正しいファイル数を表示するのはなぜですか? [コピー]

「ls|wc -l」が現在のディレクトリの正しいファイル数を表示するのはなぜですか? [コピー]

現在のディレクトリのファイル数を数えようとしたところ、ls -1 | wc -l次の意味が見つかりました。ファイルのリスト(各ファイル名が新しい行に印刷されます)をwcの入力として送信します。ここで、-l入力行数が計算されます。 。これは意味があります。

私は試してみることにしましたが、ls | wc -l正確な数のファイルが提供されて非常に驚きました。lsオプションのないコマンドはファイル名を1行に印刷するので、なぜこれが起こるのか疑問に思います。

答え1

からinfo ls

'-1'
'--format=単一列'

1行に1つのファイルを一覧表示します。 これは、標準出力が端末でない場合の「ls」のデフォルトです。

出力をパイプすると、ls各行にファイル名が与えられます。
ls出力が人の目のためだけに列単位でファイルを出力します。


ここでls何をするかを決定します。

  switch (ls_mode)
    {
    case LS_MULTI_COL:
      /* This is for the 'dir' program.  */
      format = many_per_line;
      set_quoting_style (NULL, escape_quoting_style);
      break;

    case LS_LONG_FORMAT:
      /* This is for the 'vdir' program.  */
      format = long_format;
      set_quoting_style (NULL, escape_quoting_style);
      break;

    case LS_LS:
      /* This is for the 'ls' program.  */
      if (isatty (STDOUT_FILENO))
        {
          format = many_per_line;
          /* See description of qmark_funny_chars, above.  */
          qmark_funny_chars = true;
        }
      else
        {
          format = one_per_line;
          qmark_funny_chars = false;
        }
      break;

    default:
      abort ();
    }

源泉:http://git.savannah.gnu.org/cgit/coreutils.git/tree/src/ls.c

答え2

の出力はls標準出力によって異なりますので、端子とパイプの出力が異なります。努力する

/bin/ls | cat

答え3

歴史的に、各行は出力をファイルに書き込みました。この形式lsは。wcただし、スクロールバック機能を持たない24ライン端末では、大きなリストが画面の外にスクロールする傾向があるため、目的の項目を見つけるのは困難です。だからある時点で、BSD開発者は変化した行動したがって、端末に印刷すると、ls出力形式は複数の列で指定されます。既存のシェルスクリプトが破損するのを防ぐために、パイプまたはファイルに書き込むときに以前の動作が維持されます。そして、以前の動作は、次のコマンドで出力を処理するときにwc便利です。複数列出力を端末にマージし、lsそれを端末の基本出力にすることにした決定、Rob Pikeをたくさん訓練しました。; Research Unixはバージョン8(BSDに直接基づいています)まで新機能を採用しておらず、Plan 9はlsスクリプトとlc対話型使用のための別々のコマンド、lcシェルスクリプトを介して呼び出すことができ、複数列出力を提供するコマンドに戻りましたlsmc

-1オプションは、気をつけ、少なくともユーザーが出力先に関係なく特定の出力形式を強制することを許可するための遅れた試み-Cです。ls

答え4

「ls|wc -l」が現在のディレクトリの正しいファイル数を表示するのはなぜですか?

まあ、それは間違った前提です。そうではありません!この試み:

mkdir testdir
cd testdir
# below two lines are one command, the newline is quoted so will be part of argument
echo text | tee "file
name"
ls -l
ls | wc -l

最後の行の出力は2です。

コマンドでコンソールに印刷するときls -lエルエス改行文字はそのまま印刷されず、代わりに印刷されます?。ただし、これは特別に実装された関数です。エルエス、面白いファイル名で端末を複雑にすることを避けるために、出力が実際の端末に行くことを検出したときに行われます。この同じ検出は、ファイル名が1行に1つずつ(パイプで)印刷されるのか、端末の幅(明らかに存在する場合にのみ意味がある)に基づいて印刷されるのかを決定します。はい幅のある端末)。君はだまされてエルエスls | catたとえば、元のファイル名を改行で区切って印刷する場合は、このコマンドを使用します。

wc -l行数だけカウントし、ファイル名に改行文字が含まれている場合トイレ2行で処理します。


エルエス制御文字-q/を強制的に隠すスイッチも--hide-control-charsあるためls -q | wc -l、にリストされている正確なファイル数を実際に提供する必要があります(通常、スイッチがないディレクトリの実際のlsファイル数とは異なります)。その理由は改行しかないからです。-aエルエス出力はファイル名で区切られたファイルでなければなりません。

関連情報