为什么“ls | wc -l”显示当前目录中正确的文件数量?

为什么“ls | wc -l”显示当前目录中正确的文件数量?

尝试计算当前目录中的文件数,我发现ls -1 | wc -l,这意味着:将文件列表(其中每个文件名打印在新行中)发送到 wc 的输入,其中-l将计算输入的行数。这是有道理的。

我决定简单地尝试一下ls | wc -l,并且非常惊讶它还给了我正确数量的文件。我想知道为什么会发生这种情况,因为ls没有选项的命令会在一行上打印文件名。

答案1

info ls

'-1'
'--format=单列'

每行列出一个文件。 当标准输出不是终端时,这是“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取决于 std 输出,因此终端和管道的输出有所不同。尝试

/bin/ls | cat

答案3

从历史上看,ls每行将其输出写入一个文件,这是一种方便使用其他基于文本的 Unix 工具(例如wc)进行处理的格式。然而,在没有回滚功能的 24 行终端上,大型列表往往会滚动到屏幕之外,从而很难找到您要查找的内容。因此,在某些时候,BSD 开发人员改变了行为因此,当打印到终端时,ls会将其输出格式化为多列。写入管道或文件时保留了旧的行为,以避免破坏现有的 shell 脚本 --- 并且因为在使用诸如 之类的命令处理输出时,旧的行为更有用wc。将多列输出合并到终端ls并使其成为终端上的默认输出的决定,锻炼了罗布·派克不少; Research Unix 直到第 8 版(直接基于 BSD)才采用新功能,而 Plan 9 恢复为单独的命令,ls用于脚本和lc交互式使用,通过lcshell 脚本调用和提供多列输出的ls命令。mc

-1和选项-Cls恢复理智的迟来的尝试,至少允许用户强制使用特定的输出格式,而不管输出目的地如何。

答案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 -lLS不会按原样打印换行符,而是打印?.但这是一个专门实现的功能LS,当它检测到输出将发送到实际终端时,它会执行此操作,以避免有趣的文件名弄乱终端。这一相同的检测确定文件名是每行打印一个(在管道中)还是根据终端宽度打印(这显然只有在存在时才有意义)具有宽度的终端)。你可以愚弄LS使用命令,例如ls | cat如果您想要打印原始文件名,并用换行符分隔。

wc -l只是计算行数,如果文件名恰好包含换行符,那么厕所会将其视为两行。


LS还有开关强制隐藏控制字符-q/ --hide-control-chars,因此ls -q | wc -l实际上应该给出 by 列出的文件的准确数量ls(通常与目录中的实际文件数量不同,没有-a开关),因为这样只有换行符LS输出应该是那些分隔文件名的文件。

相关内容