这是“口语UNIX”系列的第十三期:我想这是一个不祥的数字,直到我在Internet上扫描了该数字的危害性来源。 事实证明,十三个方面的“好”和“坏”比例大致相等(请参阅参考资料 )。
优点:十三是铝的原子序数,是无数解放的首选容器; 篮球职业选手威尔特·张伯伦(Wilt Chamberlain)穿了13号(你们都知道威尔特有多“幸运”); 在一种禁忌变换中,十三是第七质数,而七是非常幸运的。
坏处:绞刑架(显然)有十三步; 派对撞车者Loki和Judas第十三到达。 不管您如何将它切成两,三,四或六,一张十三张桌子都很难在餐厅坐下,这也许可以解释为什么Loki和Judas被认为是局外人。
陪审团充其量只有十三岁。 因此,除非您在13日(星期五)在位于模仿鸟巷1313号(拥有自己历史的土地)上建的办公大楼的13层阅读,否则是时候庆祝了。 现在,“说UNIX”是个满脸表情的少年。 这里有十种命令行混合和外壳斯诺克游戏,以庆祝它进入青春期。 梅泽尔电视!
临时设置环境变量
环境变量(例如EDITOR和TZ)会影响命令的结果。 (前者选择要启动的程序来编辑文本;后者指定您的时区。)通常,您在外壳启动文件中设置环境变量以影响整个外壳会话,并且可以在以下位置更改外壳会话的值:任何时候都可以使用export TZ=GMT
类的命令。
此外,您可以临时更改单个命令的环境变量的值。 只需在命令行和要运行的命令的开头设置环境变量。 例如,要更改单个命令的首选编辑器,请使用EDITOR= editor
,如下所示:
$ printenv
...
EDITOR=vi
...
$ EDITOR="pico" less bigfile
此组合在较少的情况下分页bigfile
。 如果您在less中键入v以编辑文件,则会启动pico
而不是vi
。 这是另一种实际用途:
$ date
Sun Aug 5 16:14:17 EDT 2007
$ TZ="Japan" date
Mon Aug 6 05:14:06 JST 2007
对TZ的临时更改会影响date
的即时实例如何解释系统的当前日期和时间。
发现您真正在运行什么
大量的Shell功能会影响您键入的命令名称的解释方式。 每个外壳都有各种内置命令。 PATH环境变量指定要搜索的目录的列表和顺序; 并且每个别名都充当速记。 有这么多种方式运行程序,您如何知道实际执行的是什么? 使用外壳程序的内置type
命令来揭示真相。
假设您具有以下外壳程序设置:
PATH=/bin:/usr/bin:/usr/local/bin
alias vi=pico
您可以在/ usr / bin和/ usr / local / bin中找到Perl的副本。 要查找您正在使用的Perl,请type perl
。
$ perl -v
This is perl, v5.8.7 built for darwin-2level
$ type perl
perl is /use/local/bin/perl
$ type -a perl
perl is /usr/local/bin/perl
perl is /usr/bin/perl
$ type -a -w perl
perl: command
perl: command
type perl
命令显示了如何在命令行上解释perl
命令。 在这里,/ usr / local / bin / perl是扩展名。 type -a
命令显示外壳程序知道的Perl的所有实例,这在很大程度上取决于PATH变量。
尝试type
与您通常使用一些其他的命令:
$ type -a vi
vi is an alias for pico
vi is /usr/bin/vi
$ type -a cd
cd is a shell builtin
cd is /usr/bin/cd
type
命令显示vi
实际上是pico
的别名。 type
命令还显示cd
是内置命令,在外部被复制为/ usr / bin / cd。
使查找更加便携
在过去的一年中,您已经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
. ./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
无限有用,但它具有两个隐式设置,这些设置会限制其结果(并可能使您-name
):-名称匹配区分大小写,并且文件系统遍历不遵循符号链接。
因此,开始find -name '*plan*'
的命令会忽略名称中任意位置带有字符串Plan的文件,并且当您的主目录中有一个指向音乐的符号链接指向TB级媒体时,该命令无法对音乐进行分类存储在/ media / 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*
。 要遍历调整点的层次结构,必须使用-follow
。
例如,要使find
更具可移植性并且类似于Spotlight的搜索功能,请使用-print0 -follow -iname pattern
。
轻松收集许多命令的输出
您可以使用> output
和>> output
修饰符轻松捕获命令行的>> output
,其中前者创建或覆盖文件output
,后者附加到output
。 您可以组合使用两个修饰符来生成一系列命令的笔录,这在尝试快照系统状态时非常有用,例如:
$ ps > state.`date '+%F'`
$ w >> state.`date '+%F'`
后面打勾或反引号操作符( ``
代替扩展命令。 在shell解释命令行时,将在反刻度之间运行命令,并且命令的输出将在最终扩展中使用。 这里,参数周围的单引号使它保持完整,从而防止外壳程序解释+
和%
。
在这两个命令之后,将创建文件state.YYYY-MM-DD,例如state.2007-08-05
,其内容类似于以下内容:
PID TTY TIME CMD
9997 pts/1 00:00:00 zsh
10351 pts/1 00:00:00 ps
17:56:04 up 21 days, 2:53, 2 users, load average: 0.89, 0.94, 0.91
USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT
adamgood pts/0 c-67-169-182-255 Sat17 0.00s 0.37s 0.36s pine
mstreich pts/1 cpe-071-065-224- 17:17 0.00s 0.01s 0.00s w
但是,每次键入后退标记操作都很麻烦。 您可以将序列替换为:
$ file=state.`date '+%F'`
$ ps > $file
$ w >> $file
但这只是效率更高,而且仍然容易出错,因为在第二个或后续命令中使用>
而不是>>
相当容易。 捕获一系列命令输出的最简单方法是将它们组合在大括号({})中。
$ { ps; w } > state.`date '+%F'`
运行ps
命令(列出用户当前的进程),然后运行w
(显示谁在使用计算机),然后将收集的输出捕获到文件中。
注意:您也可以在括号中嵌入命令序列以达到相同的结果。 但是,有一个重要的区别。 括号中收集的一系列命令在子shell中运行,并且不会影响当前shell的状态。
例如,您可能期望以下顺序:
$ { cd $HOME; ls
-1}; pwd
产生与以下相同的输出:
$ (cd $HOME; ls); pwd
花括号中的命令更改当前外壳程序的工作目录。 后一种技术是惰性的。 使用组合还是子Shell取决于您的意图-尽管子Shell的功能要强大得多,如下所述。
抢救子弹!
虽然通常运行一个子shell来将汇总输出通过管道传递给单个命令,但是您也可以使用子shell来在适当位置扩展命令,就像反勾号一样。 更好的是,一个子shell可以包含另一个子shell,因此扩展也可以嵌套。
让我们开始吧。
$ {ps; w} > state.$(date '+%F')
此命令与{ ps; w } > state.`date '+%F'`
{ ps; w } > state.`date '+%F'`
。 $( )
表示法在括号内运行命令,然后将其自身替换为输出。 换句话说, $()
会在适当的位置扩展,就像后退标记一样。 但是,与反向滴答不同, $( )
可能非常复杂,甚至可以包括其他$( )
扩展。 这里有些例子:
$ (cd $(grep strike /etc/passwd | cut -f6 -d':'); ls)
此命令在密码文件中搜索用户删除的条目,剪切主目录(密码文件中的字段六,如果从零开始计数的话)字段,切换到该目录并列出其内容。 grep /etc/passwd strike | cut -f6 -d':'
的输出 grep /etc/passwd strike | cut -f6 -d':'
在进行任何其他操作之前已展开到位。
这是另一个示例,这次用户名使用whoami
从环境中获取:
(cd $(grep $(whoami) /etc/passwd | cut -f6 -d':'); ls)
由于子外壳有很多用途,因此您可能更喜欢始终使用它,而不是组合使用或使用反滴答运算符。
停止输入长路径名
诸如PATH和MANPATH环境变量之类的功能可节省键入。 这两个变量都定义了一系列目录,分别用于搜索可执行文件和手册页。
该外壳程序支持另一个搜索路径:CDPATH。 顾名思义,CDPATH枚举目录列表以搜索命名目录。 让我们看看它是如何工作的。
假设您的主目录中有三个目录,分别是“墓”,“当前”和“个人”。 该墓目录包含旧的工作项目; 当前包含您积极从事的工作; 和个人包含符合您兴趣的文件等。 表演ls -R tomb current personal
发现像这样的东西:
$ ls -R tomb current personal
current:
./ ../ einstein/ herbie/
personal:
./ ../ fishing/ novel/
tomb:
./ ../ mariner/ marvin/ voyager/
在没有CDPATH的情况下,采用这种结构,更改到任何目录都要求您记住文件夹的位置,并键入其完全限定(或相对)的路径名:
$ cd ~/tomb/mariner
$ cd ~/personal/novel
$ cd ~/current/einstein
为了简化这项工作,请将CDPATH设置为您要搜索命名目录的目录列表:
$ export CDPATH=.:~/:..:../..:
这是CDPATH的最小设置。 它按顺序搜索当前目录( .
或“点”),主目录(〜/),父目录( ..
或“点点”)和祖父母目录( ../..
)。 最低设置倾向于使用本地目录和相对靠近的目录。
设置了此CDPATH后,您可以快速切换到任何顶级目录:
$ pwd
/tmp
$ cd current
/home/strike/current
$ cd personal/fishing
/home/strike/personal/fishing
$ cd novel
/home/strike/personal/novel
$ cd /tmp
$ cd personal/novel
/home/strike/personal/novel
$ cd /tmp
$ cd novel
cd: no such file or directory: novel
在除最后一个cd
命令之外的每个命令中,该参数都与CDPATH中的目录匹配。 但是,由于个人目录尚未位于CDPATH中,因此无法找到它(如果您位于相对路径之外)。
如果要搜索个人目录和其他两个目录,请在最后一个冒号之后或以您希望搜索的任何顺序将它们添加。 假设前面的export
命令在您的shell启动文件中,请添加三个目录:
$ export CDPATH=$CDPATH:~/current:~/tomb:~/personal
现在,您只需键入要切换到的目录的名称:
$ cd current
/home/strike/current
$ cd /tmp
$ cd einstein
/home/strike/current/einstein
$ cd fishing
/home/strike/personal/fishing
$ cd personal/novel
/home/strike/personal/novel
与PATH和MANPATH一样,如果CDPATH中有多个条目包含匹配项,则搜索从第一个匹配项结束。 例如,如果您将一个名为Novel的目录添加到tomb,则cd novel
命令将产生〜/ tomb / novel。
$ mkdir ~/tomb/novel
$ cd /tmp
$ cd novel
/home/strike/tomb/novel
$ cd personal/novel
/home/strike/personal/novel
当CDPATH的条目包含唯一的目录名称时,其效果最佳。 否则,请像个人/小说一样键入足够的区分路径。
减少工作量
您已经看到了许多关于在UNIX系统中广泛使用文本文件的示例。 大多数系统启动文件都是文本文件,外壳脚本,配置文件当然还有数据文件都是文本文件。 除文本编辑器外,下一个最有用的实用程序是寻呼机,或使您可以逐页浏览文本文件的应用程序。
该应用程序较少,是最受欢迎的寻呼机之一,并且它提供了大量的选项来调整其行为。 实际上,您可以将LESS环境变量设置为选项列表,以控制less的默认工作方式。 这是一组有用的选项:
export LESS="-Nmsx4"
-
-N
显示行号。 -
-m
以百分比显示文件中的当前位置。 -
-s
将多个空白行“压缩”或减少为单个空白行。 -
x4
每四个空格设置一个制表位。
花一些时间在较少的手册页上,以找到对您最有用的选项。
从下至上读取文件
UNIX系统上的许多文件会不断增长,直到被截断或存档为止。 例如,最重要的系统过程(例如电子邮件传输和远程访问)会连续记录活动,并将每个新条目附加到文件末尾。 最有趣的是日志文件的结尾。 如果服务崩溃,那么最后发生的事件将提供最多的线索。
有两种方法可以以相反的顺序显示文件中的行: tac
( cat
的反面)和命令tail -r
。
$ cat smallfile
a
b
c
$ tac smallfile
c
b
a
$ tail -r smallfile
c
b
a
您可能会发现tac
更实用,因为它发出整个文件,而不是tail
,而不是tail
,该文件将输出截断为若干行。 例如,您可以结合使用tac
和less
来创建一个别名,以反向方式分页文件:
$ alias rless="LESSOPEN='|tac %s' less"
$ rless smallfile
c
b
a
rless
别名临时将LESSOPEN(一个专门针对less的环境变量)设置为|tac %s
。 这将强制每个文件( %s
是文件名的占位符)由tac
进行预处理(因此,管道|
)。
这是相同技巧的另一种变体,但是它利用了perl
而不是tac
,这可能在您的系统上不可用:
LESSOPEN="|perl -e 'print reverse (<>)' %s" less small
perl行说:“将所有输入行读入一个匿名数组( (<>)
,反转元素的顺序,然后打印新数组。”
做新数学
如果您需要计算结果,则无需跳转到新的应用程序。 您可以在命令行中舒适地呆着。 您可以使用dc
(反抛光符号计算器)或bc
(用于数学的整个脚本语言)。 或者,如果您只是需要快速回答,请使用命令行和$(( ))
运算符。
$ echo $(( 100 / 10 ))
10
$ echo $(( 10 ** 2 ))
100
Shell并没有大量算术运算符,但是对于大多数编程任务(包括按位移位,余数和比较)而言,它就足够了。
有足够的成长空间
“说UNIX”可能是13点,但仍有很多经验。 有更多的命令和窍门可供学习,有许多概念需要探索,更不用说有大量开放源代码软件可以提高您的生产力。
哦,以免我忘了,牙套必须脱落。 高年级学生有一种仪式上的困扰,一些真正令人尴尬的时刻,并保持稳定。 或者,也许我正在显示自己的年龄。 。 。 孩子们还是会稳定下来,对吗?
谢谢阅读。 希望您到目前为止喜欢本专栏。
翻译自: https://www.ibm.com/developerworks/aix/library/au-speakingunix13/index.html