4.1《想成为黑客,不知道这些命令行可不行》(Learn Enough Command Line to Be Dangerous)—目录结构
Unix风格的目录结构通常使用一个目录名列表并用正斜杠分隔来表示,这样我们可以结合ls
命令:
$ ls /Users/mhartl/ruby
或者
$ ls /usr/local/bin
正如图20,这些表示对应的目录在一个分层的文件系统,图上意思即使mhartl是Users的子目录,而ruby是mhartl的子目录。
当谈起这些目录时根据规范会有不同: 像/Users/mhartl
的用户目录可以读作'斜杠 users斜杠mhartl'或者'斜杠users mhartl',省略原来的斜杆在发音时很常见,比如系统目录,'/usr/local/bin',发音可能是'user local bin'.由于所有的Unix目录最终都是根目录/(读作斜杠)的子目录,斜杠暗示领导和分隔。注意: 将反斜杠错用为正斜杠会带来许多痛苦,要严格避免这种错误。
对一个特殊的用户来说最重要的目录是home目录,在我的macOS系统上是/Users/mhartl,对应我的用户名(mhartl)。home目录可以被指定为绝对路径,如/Users/mhartl,也可以使用home目录的简写,即波浪线符号~(用shift加反撇号输入, 在多数键盘中位于数字1的左边)。所以在图20中显示的两种路径都是一样的:/Users/mhartl/ruby/projects与/ruby/projects一样。(有趣地是,使用波浪符号代替Home目录的原因仅是因为在早先的一些键盘中"Home"键和""键是同一个。)
除了用户目录,每个Unix系统都有程序必须的系统目录用于计算机正常操作。修改系统文件或目录需要管理员权限,也叫root
.(这里的"root"与上面提到的根目录没有关系。)管理员的权限太大,所以以root身份登录对文件可以轻易操作不太好;相反,要以root身份执行任务通常使用sudo
命令。(Box 11)
Box11. “sudo 让我TODO======”
sudo 让普通用户拥有超级管理员权限。例如, 尝试在系统目录/opt目录中创建一个文件,如下:
$ touch /opt/foo
touch: /opt/foo: Permission denied
因为普通用户没有权限修改/opt,所以命令执行失败了,但若加上sudo命令就可以执行成功:
$ sudo touch /opt/foo
Password:
正如上面显示的, 输入sudo之后,我们被提示输入用户密码,如果正确输入并且用户被赋予sudo的特权(在大多数桌面Unix系统上),那么命令会被成功执行。如图21中,开始这个模式被否认,只有使用了sudo后才能成功执行,这是计算时的共同话题。
为了验证该文件真的被创建了,可以用ls检查:
$ ls -l /opt/foo
-rw-r--r-- 1 root wheel 0 Jul 23 19:13 /opt/foo
注意普通用户可以在系统目录里ls文件(不需要sudo)而且root的名字也在列表中,表示管理员拥有该文件。(第二个术语wheel的意思有一点模糊,但是你可以在管理员这个网站上学习它。)
为了删除刚刚创建的文件,需要再次回到管理员状态:
$ rm -f /opt/foo
rm: /opt/foo: Permission denied
$ sudo !!
$ !ls
ls: /opt/foo: No such file or directory
上面的示例中第一次执行rm失败了,所以再运行sudo !!,该命令运行sudo接着之前的命令,紧跟着我们使用!ls,该命令执行了前一条ls的命令(Box9).
在英语发音中像sudo !!没有任何意义,这在语言交流时非常重要。正如Box9中提及到的,!!读作"bang bang".然而sudo读作'SOO-doo'或'SOO-doh'.两种发音都很常见。因此,我更喜欢将'sudo !!'读作"SOO-doo bang bang".
顺便提下,su在sudo原本的意义中是'super-user',但是后来被扩展使用了, 现在通常认做是'substitute user'(代替用户)。sudo因此就是“substitute user do”(代替用户执行)的结合,即默认地用户代替管理员。由于管理员可以做任何事,在图21中的命令‘sudo make me a sandwich’成功执行了,而'make me a sandwich'没有成功。
练习
1.写下你对目录~/foo/bar的发音单词。
2.在/Users/bill/sonnets该文件中,哪个是home目录?哪个是用户名?在这个等级结构中哪个是最深的目录?
3.对于一个用户名为bill的用户,/Users/bill/sonnets和~/sonnets的差别是什么?(如果有的话)