Linux高手的 20 个习惯
不良的使用模式会降低您的速度,并且通常会导致意外错误。养成这些好习惯是加强您的 UNIX命令行技能的积极步骤。
Unix 下要采用的20个好习惯为: 1) 在单个命令中创建目录树。 2) 更改路径;不要移动存档。 3) 将命令与控制操作符组合使用。 4) 谨慎引用变量。
5) 使用转义序列来管理较长的输入。 6) 在列表中对命令分组。 7) 在 find之外使用 xargs 。
8) 了解何时 grep应该执行计数——何时应该绕过。 9) 匹配输出中的某些字段,而不只是对行进行匹配。 10) 停止对 cat使用管道。
11) 使用文件名自动完成功能 (file name completion)。 12) 使用历史扩展。 13) 重用以前的参数。
14) 使用pushd 和popd 管理目录导航。 15) 查找大型文件。
16) 不使用编辑器创建临时文件。 17) 使用curl 命令行实用工具。 18) 最有效地利用正则表达式。 19) 确定当前用户。 20) 使用awk 处理数据。
1. 在单个命令中创建目录树
清单 1 演示了最常见的 UNIX 坏习惯之一:一次定义一个目录树。
清单1.坏习惯1的示例:单独定义每个目录树 ~ $ mkdir tmp ~ $ cd tmp ~/tmp $ mkdir a ~/tmp $ cd a ~/tmp/a $ mkdir b
~/tmp/a $ cd b ~/tmp/a/b/ $ mkdir c ~/tmp/a/b/ $ cd c ~/tmp/a/b/c $
使用 mkdir的 -p 选项并在单个命令中创建所有父目录及其子目录要容易得多。但是即使对于知道此选项的管理员,他们在命令行上创建子目录时也仍然束缚于逐步创建每级子目录。花时间有意识地养成这个好习惯是值得的 .
清单2.好习惯1的示例:使用一个命令来定义目录树 ~ $ mkdir -p tmp/a/b/c
您可以使用此选项来创建整个复杂的目录树(在脚本中使用是非常理想的),而不只是创建简单的层次结构。
清单3.好习惯1的另一个示例:使用一个命令来定义复杂的目录树 ~ $ mkdir -pproject/{lib/ext,bin,src,doc/{html,info,pdf},demo/stat/a}
过去,单独定义目录的唯一借口是您的 mkdir实现不支持此选项,但是在大多数系统上不再是这样了。 IBM 、AIX? 、 mkdir 、 GNU mkdir 和其他遵守单一 UNIX 规范 (Single UNIX Specification) 的系统现在都具有此选项。
对于仍然缺乏该功能的少数系统,您可以使用 mkdirhier脚本(请参见参考资料),此脚本是执行相同功能的 mkdir的包装:
~ $ mkdirhierproject/{lib/ext,bin,src,doc/{html,info,pdf},demo/stat/a}
2. 更改路径;不要移动存档
另一个不良的使用模式是将 .tar存档文件移动到某个目录,因为该目录恰好是您希望在其中提取 .tar 文件的目录。其实您根本不需要这样做。您可以随心所欲地将任何 .tar 存档文件解压缩到任何目录——这就是 -C 选项的用途。在解压缩某个存档文件时,使用 -C 选项来指定要在其中解压缩该文件的目录:
清单4.好习惯2的示例:使用选项-C来解压缩.tar存档文件 ~ $ tar xvf -C tmp/a/b/c newarc.tar.gz
相对于将存档文件移动到您希望在其中解压缩它的位置,切换到该目录,然后才解压缩它,养成使用-C的习惯则更加可取——当存档文件位于其他某个位置时尤其如此。
3. 将命令与控制操作符组合使用
您可能已经知道,在大多数 Shell中,您可以在单个命令行上通过在命令之间放置一个分号 (;) 来组合命令。该分号是 Shell 控 制操作符,虽然它对于在单个命令行上将离散的命令串联起来很有用,但它并不适用于所有情况。例如,假设您使用分号来组合两个命令,其中第二个命令的正确执行完全依赖于第一个命令的成功完成。如果第一个命令未按您预期的那样退出,第二个命令仍然会运行——结果会导致失败。相反,应该使用更适当的控制操作符(本文将描述其中的部分操作符)。只要您的 Shell 支持它们,就值得养成使用它们的习惯。
3.1 仅当另一个命令返回零退出状态时才运行某个命令
使用&&控制操作符来组合两个命令 ,以便仅当 第一个命令返回零退出状态时才运行第二个命令。换句话说,如果第一个命令运行成功,则第二个命令将运行。如果第一个命令失败,则第二个命令根本就不运行。例如:
清单5.好习惯3的示例:将命令与控制操作符组合使用 ~ $ cd tmp/a/b/c && tar xvf~/archive.tar
在此例中,存档的内容将提取到 ~/tmp/a/b/c目录中,除非该目录不存在。如果该目录不存在,则 tar 命令不会运行,因此不会提取任何内容。
3.2 仅当另一个命令返回非零退出状态时才运行某个命令
类似地,||控制操作符分隔两个命令,并且仅当第一个命令返回非零退出状态时才运行第二个命令。 换句话说,如果第一个命令成功,则第二个命令不会运行。如果第一个命令失败,则第二个命令才会 运行。在测试某个给定目录是否存在时,通常使用此操作符,如果该目录不存在,则创建它:
清单6.好习惯3的另一个示例:将命令与控制操作符组合使用 ~ $ cd tmp/a/b/c || mkdir -p tmp/a/b/c
您还可以组合使用本部分中描述的控制操作符。每个操作符都影响最后的命令运行:
清单7.好习惯3的组合示例:将命令与控制操作符组合使用
~ $ cd tmp/a/b/c || mkdir -p tmp/a/b/c&& tar xvf -C tmp/a/b/c ~/archive.tar
4. 谨慎引用变量
始终要谨慎使用Shell扩展和变量名称 。一般最好将变量调用包括在双引号中,除非您有不这样做的足够理由。类似地,如果您直接在字母数字文本后面使用变量名称,则还要确保将该变量名称包括在方括号 ([])中,以使其与周围的文本区分开来。否则, Shell 将把尾随文本解释为变量名称的一部分——并且很可能返回一个空值。清单 8 提供了变量的各种引用和非引用及其影响的示例。
清单8.好习惯4的示例:引用(和非引用)变量 ~ $ ls tmp/ a b
~ $ VAR=\~ $ echo $VAR tmp/a tmp/b ~ $ echo \tmp/*
~ $ echo $VARa ~ $ echo \~ $ echo \tmp/*a
~ $ echo ${VAR}a tmp/a ~ $
5. 使用转义序列来管理较长的输入
您或许看到过使用反斜杠 (/)来将较长的行延续到下一行的代码示例,并且您知道大多数 Shell 都将您通过反斜杠联接的后续行上键入的内容视为单个长行。然而,您可能没有在命令行中像通常那样利用此功能。如果您的终端无法正确处理多行回绕,或者您的命令行比通常小(例如在提示符下有长路经的时候),反斜杠就特别有用。反斜杠对于了解键入的长输入行的含义也非常有用,如以下示例所示:
清单9.好习惯5的示例:将反斜杠用于长输入 ~ $ cd tmp/a/b/c || / > mkdir -p tmp/a/b/c && /
> tar xvf -C tmp/a/b/c ~/archive.tar
或者,也可以使用以下配置:
清单10.好习惯5的替代示例:将反斜杠用于长输入 ~ $ cd tmp/a/b/c /
> || / > mkdir -p tmp/a/b/c / > && /
> tar xvf -C tmp/a/b/c ~/archive.tar
然而,当您将输入行划分到多行上时, Shell始终将其视为单个连续的行,因为它总是删除所有反斜杠和额外的空格。
注意:在大多数Shell中,当您按向上箭头键时,整个多行输入将重绘到单个长输入行上。
6. 在列表中对命令分组
大多数 Shell都具有在列表中对命令分组的方法,以便您能将它们的合计输出向下传递到某个管道,或者将其任何部分或全部流重定向到相同的地方。您一般可以通过在某个 Subshell 中运行一个命令列表或通过在当前 Shell 中运行一个命令列表来实现此目的。
6.1 在Subshell中运行命令列表
使用括号将命令列表包括在单个组中。这样做将在一个新的 Subshell中运行命令,并允许您重定向或收集整组命令的输出,如以下示例所示:
清单11.好习惯6的示例:在Subshell中运行命令列表 ~ $ ( cd tmp/a/b/c/ || mkdir -p tmp/a/b/c&& / > VAR=$PWD; cd ~; tar xvf -C $VARarchive.tar ) / > | mailx admin -S \
在此示例中,该存档的内容将提取到 tmp/a/b/c/目录中,同时将分组命令的输出(包括所提取文件的列表)通过邮件发送到地址 admin 。
当您在命令列表中重新定义环境变量,并且您不希望将那些定义应用于当前 Shell时,使用 Subshell 更可取。
6.2 在当前Shell中运行命令列表
将命令列表用大括号 ({})括起来,以在当前 Shell 中运行。确保在括号与实际命令之间包括空格,否则Shell 可能无法正确解释括号。此外,还要确保列表中的最后一个命令以分号结尾,如以下示例所示:
清单12.好习惯6的另一个示例:在当前Shell中运行命令列表 ~ $ { cp ${VAR}a . && chown -Rguest.guest a && / > tar cvf newarchive.tar a; } | mailx admin-S \