为什么重定向符号会改变ls的行为?

时间:2013-08-01 14:44:54

标签: linux bash unix

因此,在以下情况下,我一直怀疑重定向的工作原理:

  1. 我输入“ls”,所有文件名都用空格分隔:

    test$ touch a b c
    test$ ls
    a b c
    
  2. 我使用“>”将STDOUT重定向到文件:

    test$ ls > ls.txt
    test$ cat ls.txt 
    a
    b
    c
    ls.txt
    
  3. 有趣的是,格式发生了变化,文件名由换行符分隔。似乎输出是由ls -1生成的。

    为什么后一种情况下的输出与前一种情况不同?我实际上可以看到“>”符号所以它改变了它的行为?

3 个答案:

答案 0 :(得分:11)

ls测试其输出流以查看它是否是终端,并根据它修改其行为。

记录在案; man的{​​{1}}页面记录了几个取决于输出是否为终端的内容:

  • 如果输出是终端,则ls(对于多列输出)是默认值,否则-C(单列)是默认值。
  • 如果使用-1-l且输出是终端,则所有文件大小或块的总和将分别打印在列表之前的一行上。
  • 如果输出是终端,则-s是默认值。这会将非图形字符打印为“?”。否则,-q-v是默认值。我对-w-v之间的区别有点不清楚。我所说的文件-w强制“未经编辑的非图形字符打印”和-v强制“打印不可打印的字符。”

答案 1 :(得分:3)

它无法看到符号(由shell解释),但它可以找出输出是否转到终端。

为了将文件很好地组织到列中,ls需要知道终端的宽度。当输出设备不是终端时,它只是不知道如何格式化其输出。

此行为的另一个好处是,您可以执行ls | wc -l之类的操作,而无需担心同一行上的多个文件。 (不过,您仍然需要担心包含换行符的文件名。)

答案 2 :(得分:2)

ls使用一个名为ls_mode的内部变量,它对于Gnu coreutils实现的3 ls“type”命令是不同的。对于ls,它是LS_LS。对于dir,它是LS_MULTI_COL,对于vdir,它是LS_LONG_FORMAT。实际的ls program表示根据此变量,输出格式将发生变化。对于ls,这就是它所说的

  

如果ls_mode是LS_LS,输出格式取决于是否   输出设备是终端。这是'ls'计划。

这与您使用输出位置更改格式的体验一致。如果您对dir尝试相同的操作,则不会。