0%

Shell Basic

echo

1
2
3
4
echo one     two  three #  echo squeezes out extra blanks between words
echo "one two three"
# 没有引号时会忽略单词间的多余空格,这是因为在 Unix 系统上,单词很重要,而空格只是用来分
# 隔单词的。一般来说,Unix系统会忽略多余的空格。

Files

Unix 只识别三种类型的文件:

  • ordinary files (-)
  • directory files (d)
  • special files
    • c 字符设备文件
    • s 套接字文件
    • l 链接文件
    • b 块设备文件
    • p 管道文件

文件名不能超过 255 个字符,如果超了会截断。

目录

pwd print working directory

ln

ln from to

ls -l 第二列显示的就是一个文件的硬链接数,对于一个目录至少有两个硬链接数 ...,子目录也会增加一个对当前目录的硬链接数,子目录中有 ..

一个硬链接相当于对一个文件的引用,当文件的硬链接引用为 0 时,文件才会被删除。

突发奇想:为每个文件都创建额外的硬链接避免误删除,理论上可行,不推荐,虽然不会增加额外的磁盘空间,但是会增加目录条数,也会导致潜在的名称冲突。

概念

  • 硬链接是将一个文件名直接指向存储在磁盘上的实际数据块
  • 一个文件可以有多个硬链接,这些硬链接共享同一个数据块

实现

  • 硬链接是直接指向文件数据块的多个目录项
  • 所有的硬链接都具有相同的 inode 号,因为它们引用相同的数据块

特点

  • 硬链接是文件的一个完全副本,只不过它们共享相同的数据块
  • 删除一个硬链接不会影响数据,数据仍然可以通过其他硬链接访问,直到所有硬链接都被删除
  • 硬链接不能跨文件系统创建,只能在同一个文件系统内创建
  • 硬链接不能指向目录,避免循环引用

用途

硬链接适用于需要多个名称访问相同文件数据的场景。

概念

  • 软链接是一个文件,包含另一个文件或目录的路径信息
  • 它相当于一个指针,指向目标文件或目录

实现

  • 软链接本身是一个独立的文件,包含指向目标文件的路径
  • 软链接和目标文件具有不同的 inode 号

特点

  • 软链接可以跨文件系统创建
  • 软链接可以指向目录
  • 删除软链接不会删除目标文件,但如果删除目标文件,软链接将变为悬空链接(dangling symbolic link),指向一个不存在的路径
  • 软链接可以在系统中形成链条或循环引用,但这通常是不推荐的,因为它们可能导致循环引用问题

用途

软链接适用于创建快捷方式或指向其他文件系统和目录的场景

思考

  1. cp 一个软链接会发生什么?
    默认会复制软链接指向的文件,可以通过 -P 或者 --no-dereference(mac 使用 -R) 选项来指定复制软链接本身。

    1
    2
    3
    echo "Hello World" > original_file.txt
    ln -s original_file.txt symlink.txt
    cp -P symlink.txt copied_symlink.txt
  2. 怎么找到一个文件所有的硬链接呢?

1
2
3
ls -li file.txt
find /path/to/search -inum 123456
# 也可以通过 stat 查找文件有多少硬链接数
  1. 一个文件只有一个 inode 号,inode 维护了很多信息,包含文件所在的数据块等。

  2. 删除软链接指向的文件后,再创建相同名称的文件,软连接会恢复吗?
    会,软链接存储的是目标文件的路径,而不是目标文件的 inode。

    • 软链接指向路径:软链接始终指向指定的路径,而不是文件本身。因此,路径存在时,软链接有效;路径不存在时,软链接无效。
    • inode 变化:删除并重新创建文件会生成一个新的 inode,软链接并不关心 inode,而是关心路径是否存在。
    • 硬链接不同:硬链接指向文件的 inode,所以即使原文件被删除,硬链接仍然指向相同的 inode,文件内容不会丢失。

filename substitution

The Asterisk

会进行文件替换,比如 ls * 会列出所有文件,echo *aaa 如果没有匹配到任何文件,echo 会打印 *aaa

Matching single Characters

* 匹配0个或多个,?匹配一个。

1
2
3
4
echo ?   # 匹配单个字符的文件名
echo ?? # 匹配两个字符的文件名
echo a? # 匹配以a开头的两个字符的文件名
echo ??* # 匹配至少两个字符的文件名
1
2
3
4
[] # [] 的作用和`?` 类似
[a-z] # 所有小写字母
# List files that begin with a lowercase letter and don’t end with a digit
ls [a-z]*[!0-9]

Filename Nuances 文件名细微差别

文件名中的空格

问题是由于 shell 使用空白字符分隔单词,也就是说 echo hello world shell 会解析为调用 echo 并且有两个参数。

解决方法:转义或者加引号 cat "my test document" or cat my\ test\ document

其他特殊字符

比如文件中包含? 或者 ' 或者 " 呢,使用转义或者双引号或者单引号。

STD I/O and I/O redirection

大多数 Unix 系统的命令从屏幕(key board)获取输入,并把结果输出到屏幕。在早期,屏幕就是 terminal 终端,现在指终端软件。

比如 sort 命令在没有给出文件时会从标准输入中获取输入,也就是键盘,此时需要指定输入结束, end-of-file sequence 也就是 ctrl + d

注意:ctrl+d 是被 shell 处理的,并不会被 command 处理。

OUTPUT Redirection

> and >> 前者会覆盖目标,后者会追加写入。

cat file1 file2 > file3,这就是 cat 命令名称的由来,当使用超过一个文件时,它的作用就相当于 concatenate 多个文件。

INPUT Redirection

正如命令的输出可以重定向到文件一样,命令的输入也可以从文件重定向。当然,只有通常从标准输入获取输入的命令才能以这种方式从文件重定向其输入。

1
2
wc -l users
wc -l < users

两个命令的结果是不一样的,前者会输出文件名,这指出了两者之间的微妙差异,在第一种情况下,wc 知道它正在从文件 users 读取输入。
在第二种情况下,它只能看到通过标准输入提供给它的原始数据。就 wc 而言,它不知道它的输入是来自终端还是来自文件,只知道是标准输入,
因此它无法报告文件名!

标准错误

大多数情况下,我们很少关心标准错误和标准输出的区别,标准错误会把错误信息也打印到终端。但是还是有一些区别的。

1
2
3
# 即使重定向了,但是错误信息不会出现在文件中
ls n* > foo
# 要想错误信息也出现在文件中,可以使用 2>,中间不能有空格

Pipes

把一个命令的标准输出连接到下一个命令的标准输入中。

1
2
# 统计文件数量,ls 在和管道一起时会改变其输出格式 ls | cat
ls | wc -l

其他

一次可以执行多个命令,中间用分号分开。

后台

Sending a Command to the Background。正常情况下,我们在终端输入命令并且等待结果,有些命令执行时间很短,
但有些命令需要很长的时间,这就妨碍我们做其他事情(可能早期终端和现在不一样,现在再打开一个终端就行),此时就需要后台执行。

使用 & 符号可以把命令放到后台执行,如果没有任何重定向,那么后台命令的输入依然会出现在终端,如果它需要从标准输入获取信息,那么会停在终端等待输入。

执行后会返回两个数字,第一个是 job id,第二个是 pid。