Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
144 changes: 144 additions & 0 deletions docs/Ch03/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -488,6 +488,57 @@ Ubuntu 官方源位于国外,往往会有速度与延迟上的限制,可以

在 Linux 在进行操作文件与目录是使用 Linux 最基础的一个技能。不像在 Windows 和 macOS 下有图形化界面,拖拽文件即可完成文件的移动,很容易管理文件与目录,Linux 的命令行操作虽然繁琐一些,但一旦上手,就可以通过命令与参数的组合完成通过图形化界面难以实现或者无法实现的功能。

### 查看文件夹内容 {#ls}

[第二章](../Ch02/index.md)已经介绍过 `ls` 的基本用法,这里再补充一些常用的选项。

```console
$ # -l 参数会以列表的形式输出文件的详细信息
$ ls -l [DIRECTORY]
$ # -a 参数会显示所有文件,包括隐藏文件(以 . 开头的文件)
$ ls -a [DIRECTORY]
$ # -h 参数会以人类可读的方式显示文件大小,例如 1K、234M、2G 等
$ ls -h [DIRECTORY]
```

!!! example "ls 示例"

* 以列表的形式显示当前目录下的所有文件(包括隐藏文件)

```console
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这层额外的缩进是否可以用 code block 的 title 代替?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

另外 VS Code 的某个插件会提示 console 语言适用于同时展示命令及其输出的场景,而非只展示命令。不过这似乎是本书约定?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

另外 VS Code 的某个插件会提示 console 语言适用于同时展示命令及其输出的场景,而非只展示命令。不过这似乎是本书约定?

对,这个规则我加到忽略列表里面了,至于要不要改可以讨论。

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这层额外的缩进是否可以用 code block 的 title 代替?

image image

确实更好看一些。这一章的我改掉吧。

$ ls -la
```

* 以人类可读的方式显示当前目录下的所有文件(包括隐藏文件)的详细信息

```console
$ ls -lha
```

!!! tip "tree"

`tree` 命令可以以树状图的形式显示目录结构,使用前需要先安装:

```console
$ sudo apt install tree
```

使用方法:

```console
$ tree [DIRECTORY]
```

!!! tip "eza"

[eza](https://github.com/eza-community/eza) 是一个 `ls` 的替代品,输出更加好看。可以使用如下命令安装:

```console
$ sudo apt install eza
```

其使用方法和 `ls` 基本相同,例如显示详细信息则使用 `eza -l`。

### 查看文件内容 {#view}

#### cat {#cat}
Expand Down Expand Up @@ -515,6 +566,20 @@ $ cat [OPTION] FILE

当然和猫咪没有关系,cat 这里是 con**cat**enate(连接)的缩写,因为 cat 工具实际的功能是连接多个文件,然后输出。但是当只有一个文件的时候,cat 就会直接输出这个文件,所以 cat 最常见的用途就是输出单个文件。

!!! tip "bat"

[bat](https://github.com/sharkdp/bat) 是一个 `cat` 的替代品,输出支持语法高亮和分页。可以使用如下命令安装:

```console
$ sudo apt install bat
```

例如,输出 sol1.c 文件的内容(支持 C 语言语法高亮):

```console
$ bat sol1.c
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bat 包在 deb/uuu 下提供的命令是 /usr/bin/batcat,需要另外配置 symlink / alias

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oops

```

#### less {#less}

less 和 cat 的区别在于,cat 会一次性打印全部内容到终端中并退出,而 less 一次只显示一页,且支持向前/后滚动、搜索等功能。如果要在一个大文件中(例如 man page)查找一部分内容,less 通常要比 cat 方便得多。
Expand Down Expand Up @@ -777,6 +842,8 @@ $ find [OPTION] PATH [EXPRESSION]
| `-size +1M` | 大于 1M 的文件,`+` 代表大于这个大小,对应地,`-` 代表小于之后的大小 |
| `-or` | 或运算符,代表它前后两个条件满足一个即可 |

如果不添加任何其他选项,find 会递归地输出提供的 PATH 下的所有文件。

!!! example "搜索示例"

* 在当前目录搜索名为 report.pdf 的文件:
Expand All @@ -797,6 +864,83 @@ $ find [OPTION] PATH [EXPRESSION]
$ find ~/ -name 'node_modules' -type d
```

!!! tip "对搜索到的文件批量执行命令"

find 的一个很有用的用法是对每一个文件都执行某个命令(例如 `md5sum`):

```shell
find . -type f -exec md5sum {} \;
```

这里,`find .` 是指对当前目录(`.`)进行 `find`,并只列出文件(`-type f`)。`-exec` 后面的内容是要执行的命令,其中 `{}` 会被替换成找到的对象(文件、目录)的路径,`\;` 表示对每个对象都执行一次给定的命令,即实际运行的是:

```shell
md5sum file1
md5sum file2
md5sum file3
...
```

如果将 `\;` 换成 `+`,那么就是将文件名称收集起来一并交给要执行的命令,即:

```shell
md5sum file1 file2 file3 ...
```

!!! tip "fd"

[fd](https://github.com/sharkdp/fd) 是 find 的更现代、好用的替代。在 Ubuntu 下需要安装 `fd-find` 包,并且命令名为 **`fdfind`**(而非 `fd`)。

其默认接受正则表达式(见[第九章](../Ch09/index.md))作为搜索条件,例如搜索结尾为 `.conf` 的文件:

```console
$ fdfind '\.conf$' /etc/
/etc/debconf.conf
/etc/gai.conf
/etc/host.conf
(以下省略)
```

### 统计文件或文件夹大小 {#du}

`du` 命令可以统计文件和目录的大小。目录的大小是无法直接获取的,需要统计里面所有的文件和子目录的大小之后加和才能得到。`du` 命令的输出类似这样:

```console
$ du -h /etc/
4.0K /etc/initramfs-tools/hooks
8.0K /etc/initramfs-tools/conf.d
4.0K /etc/initramfs-tools/scripts/local-premount
4.0K /etc/initramfs-tools/scripts/nfs-premount
(中间内容省略)
4.0K /etc/initramfs-tools/scripts/panic
4.0K /etc/initramfs-tools/scripts/local-top
44K /etc/initramfs-tools/scripts
72K /etc/initramfs-tools
12K /etc/udisks2
16K /etc/fonts/conf.d
60K /etc/fonts/conf.avail
84K /etc/fonts
```

由于前面说到的原因,`du` 需要先递归进入子目录,处理完其中所有的项目之后,才能回到上层目录并显示上层目录的总大小。

此外,`ncdu` 命令可以以图形化和交互式的方式显示目录的内容和大小,并可以用左右方向键浏览目录,类似 Windows 的文件资源管理器。这非常便于观察哪个目录占用了较大的磁盘空间。按 `d` 可以删除当前选中的文件或目录,按 `q` 退出。

```plain
ncdu 1.18 ~ Use the arrow keys to navigate, press ? for help
--- /home/example/path -------------------------------------
53.1 MiB [##########] /main
45.4 MiB [######## ] Contents-riscv64.gz
40.6 MiB [####### ] /universe
580.0 KiB [ ] /multiverse
44.0 KiB [ ] /restricted
8.0 KiB [ ] InRelease
8.0 KiB [ ] Release
4.0 KiB [ ] Release.gpg

Total disk usage: 139.7 MiB Apparent size: 139.6 MiB Items: 29
```

### 模式匹配 {#pattern}

许多现代的 shell 都支持一定程度的模式匹配。举个例子,bash 的匹配模式被称为 [glob](https://mywiki.wooledge.org/glob),支持的操作如下:
Expand Down
93 changes: 4 additions & 89 deletions docs/Ch05/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,10 @@ graph LR

当然,实际情况不一定会和以下介绍的内容完全一致。可以使用 `man hier` 和 `man file-hierarchy` 查看你的系统中关于文件系统层次结构的文档。

??? note "Systemd 的文件系统层次结构"

如果你阅读了 `man hier` 和 `man file-hierarchy`,你会发现它们之间有一些差异。例如后者有 `/efi` 目录,前者未提及。这是因为后者是 Systemd 使用的文件系统层次结构,在 FHS 的基础上做了一些扩展。但是总体来说,两者是类似的。

`/bin`
: 存储必须的程序文件,对所有用户都可用。

Expand Down Expand Up @@ -455,95 +459,6 @@ graph LR
- `/var/run`:存储程序运行时的数据(部分发行版会将该目录符号链接到 `/run` 目录)。
- `/var/spool`:存储「等待进一步处理」的程序数据。

## 列出文件系统项目 {#list-objects}

经常我们需要在 Shell 中列出某个目录下的项目(子目录和文件)。`ls` 命令是最常见的用来列出文件系统项目的命令,`ls -la` 则可以显示隐藏文件(`-a`)和更详细的信息(`-l`)。但是,`ls` 只能显示某个目录下的文件和子目录,并不会深入子目录内部继续检查。下面介绍几个命令,常用于获取这些信息。

### `find` 命令 {#cmd-find}

`find` 命令可以列出某个目录下所有的目录和文件,并**递归地**进入子目录。基本用法是

```shell
$ find /etc
/etc
/etc/analog.cfg
/etc/hosts.deny
/etc/initramfs-tools
/etc/initramfs-tools/initramfs.conf
/etc/initramfs-tools/hooks
/etc/initramfs-tools/conf.d
/etc/initramfs-tools/conf.d/resume
/etc/initramfs-tools/modules
/etc/initramfs-tools/update-initramfs.conf
... (省略)
```

可以看到,`find` 命令将列出指定的目录下的文件和子目录名称,在遇到子目录时立即进入目录并递归地执行上面的操作。

该命令的一个很有用的用法是对每一个文件都执行某个命令(例如 `md5sum`):

```shell
find . -type f -exec md5sum {} \;
```

这里,`find .` 是指对当前目录(`.`)进行 `find`,并只列出文件(`-type f`)。`-exec` 后面的内容是要执行的命令,其中 `{}` 会被替换成找到的对象(文件、目录)的路径,`\;` 表示对每个对象都执行一次给定的命令,即实际运行的是

```shell
md5sum file1
md5sum file2
md5sum file3
...
```

如果将 `\;` 换成 `+`,那么就是将文件名称收集起来一并交给要执行的命令,即

```shell
md5sum file1 file2 file3 ...
```

### `du` 命令 {#cmd-du}

`du` 命令可以统计文件和目录的大小。目录的大小是无法直接获取的,需要统计里面所有的文件和子目录的大小之后加和才能得到。`du` 命令的输出类似这样:

```shell
$ du -h /etc/
4.0K /etc/initramfs-tools/hooks
8.0K /etc/initramfs-tools/conf.d
4.0K /etc/initramfs-tools/scripts/local-premount
4.0K /etc/initramfs-tools/scripts/nfs-premount
... (省略)
4.0K /etc/initramfs-tools/scripts/panic
4.0K /etc/initramfs-tools/scripts/local-top
44K /etc/initramfs-tools/scripts
72K /etc/initramfs-tools
12K /etc/udisks2
16K /etc/fonts/conf.d
60K /etc/fonts/conf.avail
84K /etc/fonts
```

由于前面说到的原因,`du` 需要先递归进入子目录,处理完其中所有的项目之后,才能回到上层目录并显示上层目录的总大小。类似 `ls -h`,这里的 `-h` 表示以人类可读的方式进行显示,`-b` 则可以显示字节数,`-a` 可以使得输出包含文件的大小(默认只显示各层级目录的大小)。

### `ncdu` 命令 {#cmd-ncdu}

`ncdu` 命令可以以图形化和交互式的方式显示目录的内容和大小,并可以用左右方向键浏览目录,类似 Windows 的文件资源管理器。这非常便于观察哪个目录占用了较大的磁盘空间。

```plain
ncdu 1.18 ~ Use the arrow keys to navigate, press ? for help
--- /home/xxxxxx(略去) -----------------
/..
53.1 MiB [##########] /main
45.4 MiB [######## ] Contents-riscv64.gz
40.6 MiB [####### ] /universe
580.0 KiB [ ] /multiverse
44.0 KiB [ ] /restricted
8.0 KiB [ ] InRelease
8.0 KiB [ ] Release
4.0 KiB [ ] Release.gpg

Total disk usage: 139.7 MiB Apparent size: 139.6 MiB Items: 29
```

## 思考题 {#questions}

!!! question "nobody 用户"
Expand Down
17 changes: 17 additions & 0 deletions docs/Ch06/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,23 @@ $ grep -R 'hello' . # 递归查找当前目录下内容包含 hello 的文件

grep 事实上是非常强大的查找工具,[第九章](../Ch09/index.md)将在介绍正则表达式语法之后进一步介绍 grep。

!!! tip "ripgrep"

除了 grep 以外,还有一个更快更强大的工具 [ripgrep](https://github.com/BurntSushi/ripgrep)。其会默认递归查找当前目录下的文件。安装 `ripgrep` 包后使用 `rg` 命令,即可作为 `grep -R` 的替代:

```console
$ # 在 /etc/ 下搜索包含 localhost 的文件
$ rg localhost /etc/
/etc/hosts
1:127.0.0.1 localhost
2:::1 localhost

/etc/security/pam_env.conf
52:# to "localhost" rather than not being set at all
53:#REMOTEHOST DEFAULT=localhost OVERRIDE=@{PAM_RHOST}
64:#NNTPSERVER DEFAULT=localhost
```

### 文本替换:sed {#sed}

`sed` 命令可以替换文本中的字符串:
Expand Down