对话 UNIX,第 13 部分: 另外十种命令行组合( 二 )


使得 find 命令具有更好的可移植性
去年曾经介绍了许多关于 find 的使用的内容,但是我忽略了其中的一个选项,它使得 find 命令行可以移植到其他操作系统 。
通常,Unix?系统中很少使用带空格的文件名 。然而,在 Mac OS X 和 Microsoft?Windows?中常常使用更长的、更具描述性的文件名,并且在 UNIX 中它们也变得越来越多,这是因为该操作系统不断地积聚更多的桌面特性 。毕竟,将一份报告保存为 2007 Business Plan 明显要比 bizplan07.ooo 好得多 。
find 命令使用嵌入的特殊字符列举长文件名,但是,如果您希望将 find 与另一个命令组合使用,那么最安全的方法是,使用 NUL 字符(而不是空格)分隔列表中的每个文件名 。让我们来了解其中的差异 。
我们假设您拥有三个文件夹,其中一个或者多个目录的名称中包含空格:
$ ls -1
Business Plan 2007
Expense Report
Pictures from Spain
如果您对大量的文件运行 find 命令,并且将结果列表传递给 xargs,那么文件名中的空格将会导致错误:
$ find . -type f -print | xargs ls -1
ls: ./Business: No such file or Directory
ls: ./Expense: No such file or directory
ls: ./Pictures: No such file or directory
ls: 2007: No such file or directory
ls: Plan: No such file or directory
ls: Report: No such file or directory
ls: Spain: No such file or directory
ls: from: No such file or directory
传递给 xargs 的结果是单个字符串 . ./Business Plan 2007 ./Expense Report ./Pictures from Spain 。在缺省情况下,xargs 将使用空格(或者换行符)对输入字符串进行划分,以便产生可以进行操作的一个文件列表 。在这个示例中,因为文件名中包含空格,所以这样做将会产生错误的列表,如前所述 。
一种适当的、可移植的技术是使用 find -print0,加上 xargs -0,以便使用 NUL 字符对文件名进行划分 。下面是这种推荐的方法:
$ find . -type f -print0 | xargs -0 ls -1
./Business Plan 2007
./Expense Report
./Pictures from Spain
另外,如果您希望预览 xargs 产生的命令,可以添加选项 -p 或者 -t 。-p 选项显示每个合成的命令,并提示您进行确认 。输入大写的或者小写的 y 以便运行命令,输入任何其他的内容可以拒绝该命令 。-t 选项可以在执行每个命令之前将命令回显到 stderr 。
更充分地利用 find 命令
尽管 find 非常有用,但是有两个隐含的设置可能会限制它的结果(并使得您不知所措):-name 匹配是区分大小写的,并且不会根据符号链接对文件系统进行遍历 。
因此,一个以 find -name '*plan*' 开头的命令将忽略名称中包含 Plan 字符串的文件,假设您的 home 目录中包含名为 music 的符号链接,而它指向装入到 /media/music 的 TB 级的存储介质,那么这个命令将不会列出您的符号链接 music 。
您可以使用 -iname 覆盖区分大小写的匹配,并且您可以使用 -follow 根据符号链接进行遍历 。下面是使用了这两种选项的一个示例:
$ alias ls='ls -aF'
$ ls -1
bin/
lib/
src/
tomb/
tunes@
$ find . -name '*music*' -type f -print
$ find . -iname '*music*' -type f -print
$ find . -name '*music*' -type f -follow -print
$ find . -iname '*music*' -type f -follow -print
./tunes/Muse/Origin Of Symmetry/04 Hyper Music.m4a
./tunes/Radiohead/OK Computer/04 Exit Music (For A Film).MP3
正如 -F 选项生成的 @ 符号注释所表示的,tunes 是一个符号链接 。要查找名称中包含字符串“music的任何变体的所有歌曲,您必须使用 -iname *music* 。要遍历到 tunes 所指向的文件系统层次结构,您必须使用 -follow 。

推荐阅读