当前位置:Linux教程 - Linux - 讨厌的ls不能随意显示子目录

讨厌的ls不能随意显示子目录

  ls 是最为熟知的 Unix 命令之一(犹如 DOS 里的 dir ),大家都已经习惯了它的许多用法。乍听“讨厌”二字,你可能接受不了。然而,锤炼了这么久的 ls 程序,也许从一开始就存在着明显的毛病。当你不带参数使用 ls 时,它能如你所愿,列出当前目录下的所有文件和目录名(点文件除外)。这时如果你发现列出的东西太多,想缩小一下范围,自然就想到使用 ls a* 之类的命令。遗憾的是,这条命令列出的东西常常(不是少了,而是)更多!(多到令人气愤的程度!)因为它不仅列出了以 a 打头的文件名,而且也列出了以 a 打头的目录中的(全部!)文件,这是你一点也不感兴趣的,因为你极少要求将当前目录中的部分文件和某些一级子目录中的所有文件一并列出,这样的组合是很古怪的。你顶多对 -R 选项感兴趣,它是请求列出整个目录树(包括所有子目录中的文件)。作为文件列表的专用命令,如果像 ls 这样不能“善解人意”的话,那么说它“讨厌”也不算太过分吧!

  也许有的朋友会说,-d 参数可以抑制子目录内容的输出,即用 ls -d a* 可以达到目的。然而问题是,对于如此频繁使用的命令来说,时常敲入 -d 是一件烦琐的事,绝对不能令人接受。多数情况是,先使用了 ls a*;待发现苗头不对时,才准备使用 ls -d a* ;而这时屏幕上早已混乱不堪,不可能再用鼠标去快捷地选用先前屏幕上你想要的文本了。 有朋友说,可以利用 shell 的别名机制,将 ls 重定义为 ls -d ;然而在目前,这又会带来其它的问题。

  首先,ls -d 会将所有的目录内容都隐去,例如:ls -d mydir 将只产生一个结果,就是 mydir 本身而不是目录的内容,而你想要的恰恰是 mydir 包含的文件。这时你大概没有办法了,因为你已经将 ls 重定义为 ls -d 了,并且不存在专门撤销 -d 选项的其它选项。虽然你可以用 “ls” 来暂时绕过别名,但如此拐弯抹角,不是同样令人难受吗?

  其次,要想简单地列出 mydir 所包含的全部目录项(包括点文件)几乎是不可能的。仅仅用 ls -ad mydir/* 是不行的,因为由 shell 解释的 * 号是不包括点文件的(暂不讨论 shell 的 dotglob 选项,事实上人们极少使用这一选项)。有的人使用许许多多的别名,代表不同的参数选项,如 ll, la, ld 等等,但是多记忆一条命令也是一个负担,而且不标准,不通用,还可能与别的命令名相冲突。可见在旧的 ls 框架下,重定义不能带来预期的好处。

  总之,ls 使我们受到很大的约束,是极不理想的。多年来,大家各自都有权宜之计,但都不想从根本上改变它。看来这一“重”任落到了我们这些无名小卒身上。是的,我们是非改不可的;因为我们要营造完美的系统,它是我们的珍爱,它是我们的家!!

  如果你深有同感,而且喜欢大胆尝试,那么新的 ls 已为你做好,现在你就能如愿以偿了!

  首先请下载:

http://metalab.unc.edu/pub/gnu/fileutils/fileutils-4.0.tar.gz

(压缩大小 1.1 MBytes)

然后下载 ls 的补丁( 2000-01-01 创建,压缩大小 2707 字节)。该补丁实际上是 fileutils 的补丁。用 tar, gzip, gunzip, patch, make 等命令进行解包、修补和编译,生成新的 ls 执行程序。修补后的 ls 同旧的 ls 保持了极大的兼容性(但不是100%的兼容)。当不用 -d 选项时,两者完全等价;当使用 -d 选项时,两者也只有细微的差别。由于 ls 是一个系统命令,兼容性是至关重要的,希望这点差别不至于使系统的运行有任何失常。请朋友们将旧的 ls 留一个备份(重要哟!),万一系统出了毛病,只需要简单地恢复旧有的 ls 即可。下面详细说明带 -d 选项的新旧 ls 的差别。

  1.不带文件名参数的旧的 ls -d 列出当前目录项本身,而不是当前目录中的全部文件;不带文件名参数的新的 ls -d 列出当前目录中的全部文件,而不是当前目录项本身。

  说明:无论是否有 -d 选项,不带文件名参数的新的 ls 都列出当前目录中的全部文件,而不是当前目录项本身;因为这正是我们最频繁遇到的情况。相反,仅仅请求“列出当前目录项本身”,这是个不常用的操作,可以用带有点参数的 “ls -d .” 来实现。

  2.带有文件名参数的旧的 ls -d 总是列出目录项本身,而不是目录的内容。

  3.带有文件名参数的新的 ls -d 能够区分命令行中的目录名是否以 “/”结尾。这个 “/” 号表示请求列出子目录的内容,不列出该目录项本身。否则,如果不以 “/”结尾,那么总是列出目录项本身,而不是子目录的内容。输出的方式完全由目录名结尾是否有“/”号来决定。

  说明:根据这条规则,“ls -d /” 将列出根目录的内容,而“ls -d /.”只列出根目录项本身。在命令行中,以 “/” 结尾的和不以“/”结尾的诸多目录名可以任意混用。对于那些不以“/”结尾的目录名参数来说,新旧 ls -d 的输出结果没有任何差别。所以,新旧 ls 的整体差别很小。

4. 新的 ls -d -R mydir 或 ls -d -R mydir/ 中的 -R 选项使得 -d 选项不起作用,递归地列出 mydir 及其任一级子目录中的全部文件。旧的 ls -d -R mydir 或 ls -d -R mydir/ 中的 -d 选项优先,仅仅列出 mydir 这个目录项。

  说明:假定我们已经将 ls 重定义为“ls -d ” ,那么新的 ls 程序使我们可以用 ls -R mydir 来列出整棵目录树的内容,而不必担心其中 -d 的抑制作用。

  建议:在个人初始化文件中用别名机制重定义 ls 为 ls -d,以便利用新的 ls 所带来的好处。现在,你可以自由地在目录名尾部加上“/” 或“/.”或什么也不加,来控制 ls 以你所要的方式进行输出。本文开头提到的不伦不类的文件列表组合,现在不再出现了。现在的“ls a*”(注意其中的 ls 内含 -d 选项,否则将与旧 ls 的效果相同)只列出当前目录下以 a 打头的项目,不再混杂着子目录中的文件。另外,你已经看到,在新的 ls 框架下,代表“当前目录”的特殊目录名“.”可以发挥重要的作用。