# 目录与路径

# 相对路径与绝对路径

  • 绝对路径:由根目录开头,如 /home/mrcode
  • 相对路径:不是由根目录开头的,如 ./mrcode

# 目录的相关操作

以下的特殊目录需要着重了掌握

  • .:代表此层目录
  • ..:上一层目录
  • -:前一个工作目录
  • ~:目前用户身份坐在的家目录
  • ~account:表示 account 这个用户的家目录(account 是个账户名称)

需要特别注意的是,在所有目录下都会看到两个目录 . 与 ..,当前目录和上一层目录。

那么 linux 中,根目录有没有上层目录存在?

[mrcode@study ~]$ ls -al /
# 可以看到这两个目录的属性一模一样,所以这两个目录其实都是同一个目录
dr-xr-xr-x.  17 root root  224 Oct  4 18:31 .
dr-xr-xr-x.  17 root root  224 Oct  4 18:31 ..
1
2
3
4

那么下面讲解下几个常见的处理目录的指令:

  • cd:变换目录
  • pwd:显示当前目录
  • mkdir:建立一个新的目录
  • rmdir:删除一个空的目录

# cd(change directory)变换目录

Last login: Fri Oct 11 04:01:50 2019 from 192.168.0.105
# 登录 linux 后,每个账号都会在自己账号的家目录下
[mrcode@study ~]$ cd ../  # 注意看前面的符号 ~,这个表示在 家里
# 上面使用 cd ../ 进入了上一层目录,那么这里 ~ 变成了 home。实际路径是  /home/账户家
# 这里直接使用 cd 不带参数,会默认回到家目录中
[mrcode@study home]$ cd  
[mrcode@study ~]$
# 现在在家,返回前一个目录,也就是 /home 目录
[mrcode@study ~]$ cd -
/home
# 上次是从家出来的,这里再返回前一个目录,就又回到了家的目录中
[mrcode@study home]$ cd -
/home/mrcode
1
2
3
4
5
6
7
8
9
10
11
12
13

# pwd(print Working Directory) 显示当前所在目录

[mrcode@study mail]$ pwd
/var/mail
# 带参数 P 是显示真实的路径,而不是连接(link)路径,然而 /var/mail 就是一个连接路径
[mrcode@study mail]$ pwd -P
/var/spool/mail
# 通过命令也能看到,连接到了 spool/mail 目录中
[mrcode@study mail]$ ls -ld /var/mail
lrwxrwxrwx. 1 root root 10 Oct  4 18:21 /var/mail -> spool/mail
1
2
3
4
5
6
7
8

# mkdir 建立新目录

语法如下

mkdir [-mp] 目录名称

-m:配置文件案的权限,直接设定,不需要看预设权限(umask)的脸色
-p:将该路径上所有的目录都创建出来(当然不存在的话)
1
2
3
4

练习

# 进入临时目录
[mrcode@study ~]$ cd /tmp/
[mrcode@study tmp]$ mkdir test
# 不带参数 -p 不能创建多级目录
[mrcode@study tmp]$ mkdir test1/test2/test3/test4
mkdir: cannot create directory ‘test1/test2/test3/test4’: No such file or directory
[mrcode@study tmp]$ mkdir -p test1/test2/test3/test4

# 创建目录时直接配置该目录的权限
[mrcode@study tmp]$ mkdir -m 711 test2
[mrcode@study tmp]$ ls -ld test*
# 这些是创建目录默认的权限
drwxrwxr-x. 2 mrcode mrcode  6 Oct 11 04:32 test
drwxrwxr-x. 3 mrcode mrcode 19 Oct 11 04:33 test1
# 这个是创建目录时直接配置的权限
drwx--x--x. 2 mrcode mrcode  6 Oct 11 04:35 test2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

# rmdir 删除空的目录

语法如下

rmdir [-p] 目录名称

-p:「上层」的「空目录」也一起删除
1
2
3

练习

[mrcode@study tmp]$ ls -ld test*
drwxrwxr-x. 2 mrcode mrcode  6 Oct 11 04:32 test
drwxrwxr-x. 3 mrcode mrcode 19 Oct 11 04:33 test1
drwx--x--x. 2 mrcode mrcode  6 Oct 11 04:35 test2
# 该目录下无数据,可直接删除
[mrcode@study tmp]$ rmdir test
# 该目录下由多个目录,就无法阐述了,会报错
[mrcode@study tmp]$ rmdir test1
rmdir: failed to remove ‘test1’: Directory not empty
# 这里使用 -p 删除最后一个目录,但是当再次查看的时候,test4 的上层空的目录都不在了
[mrcode@study tmp]$ rmdir -p test1/test2/test3/test4/
[mrcode@study tmp]$ ls -ld test*
drwx--x--x. 2 mrcode mrcode 6 Oct 11 04:35 test2

# -p 删除上级空目录是什么意思,下面再来体验下

# 创建了多个目录
[mrcode@study tmp]$ mkdir -p test1/test2/test3/test4
# 然后在 test1 中创建了一个 txt 文件
[mrcode@study tmp]$ touch test1/txt
# 删除的时候,就报错了,无法删除 test1,因为该目录下有 txt 文件
# 但是注意,只是 test1 没有被删除, test2、test3、test4 还是被删除了的
[mrcode@study tmp]$ rmdir -p test1/test2/test3/test4/
rmdir: failed to remove directory ‘test1’: Directory not empty
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

但是如果想把该目录下所有的东西都删除呢?你可以使用指令 rm -r test1 就能全部删掉了, 相对来说,rmdir 没有这么危险

# 关于执行文件路径的变量:$PATH

前面讲解 FHS 后,我们知道 ls 指令完整文件名为 /bin/ls(这是绝对路径), 那么为什么我们可以在任何地方执行 /bin/ls 这个指令呢?这是因为换了变量 PATH 的能力

当我们执行一个指令的时候,系统会按照 PATH 的设定去每个 PATH 定义的目录下搜索对应的可执行文件 (比如 ls),如果在 PATH 定义的目录中含有多个文件名为 ls 的可执行文件,那么先搜索到的被执行

# 打印变量的信息,使用 echo ,「$」表示接一个变量
[mrcode@study tmp]$ echo $PATH
/usr/lib64/qt-3.3/bin:/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/mrcode/.local/bin:/home/mrcode/bin

# 注意,每个账户的 path 值也是不一样的
[root@study ~]# echo $PATH
/usr/lib64/qt-3.3/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin

1
2
3
4
5
6
7
8

仔细看上面的输出,无论哪个账户都有 /bin 或 /usr/bin 在 PATH 变量内。所以可以在任何地方使用 ls 指令

下面来几个范例来让你了解 PATH 很重要!

# 先把 ls 移动到 /bin 目录之外去,再运行 ls 看能不能运行?
[root@study ~]# mv /bin/ls ../
[root@study ~]# ls
bash: ls: 未找到命令...
相似命令是: 'lz'
# 现在已经报错找不到命令了,是因为 / 并不再 PATH 变量中

# 但是可以通过路径来运行
[root@study ~]# /l
lib/   lib64/ ls    # ls 的确被移动到 根目录下了
# 这里直接通过绝对路径运行指令
[root@study ~]# /ls
anaconda-ks.cfg  initial-setup-ks.cfg  initial-setup-ks-mrcode.cfg

# 要想不用绝对/相对路径也能使用 ls ,那么将 根目录加入到 PATH 中即可
# 也可以使用 PATH="${PATH}:/"  来配置
[root@study ~]# PATH="$PATH:/"
[root@study ~]# ls
anaconda-ks.cfg  initial-setup-ks.cfg  initial-setup-ks-mrcode.cfg

# 把 ls 移回原来的目录
[root@study ~]# mv /ls /bin/
# 可能会出现找不到指令了,没有关系,可能是因为指令参数被快取得关系
# 只要 exit 再登入 su -  就可以使用了
# 另外说一句,刚刚在命令行中把根目录添加到 PATH 中,不是永久的,退出后,再登录就失效了
[root@study ~]# ls
-bash: /ls: 没有那个文件或目录

# 假设 /usr/local/bin/ls 与 /bin/ls 两个指令,哪个先被执行?
# 可以使用 echo $PATH 或则 ${PATH} 直接显示某一个变量
[root@study ~]# ${PATH}
# 这里看哪一个目录在最前面,就是哪个目录下的 ls 先执行
-bash: /usr/lib64/qt-3.3/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin: 没有那个文件或目录
[root@study ~]# PATH
bash: PATH: 未找到命令...

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36

为什么不建议把 . 当前目录添加到 PATH 路径中?这其实是为了安全起见,不建议添加到 PATH 中, 比如在 /tmp 目录下,因为是大家都可以写的,有人搞破坏,写了一个 ls 的指令,但是里面写的是删除文件的, 这样就会先收到这个恶意的命令

由上面的示例,我们可以知道几件事情:

  • 不同身份使用者预设的 PATH 不同,默认能够随意执行的指令也不同(如 root 与 mrcode)
  • PATH 是可以修改的
  • 使用绝对路径或相对路径直接指定某个指令文件名来执行,会比搜寻 PATH 来的正确
  • 指令应该要放置到正确的目录下,执行才比较方便
  • 当前目录「.」建议不要放到 PATH 中

与 PATH 更详细的变量会在后续的 bash shell 中详细说明