Lecture1: The Bash Shell

打开bash shell,你将看到一个提示符,一般是这样的:

1
tye2007@YourComputer:~$

这个提示符告诉你当前的用户名(tye2007)、计算机名(YourComputer)以及当前所在的目录(~,表示用户的主目录)。在提示符后面,你可以输入命令来与计算机交互。$符号表明你当前不是root用户。

基本命令

我们输入下面的命令:

1
tye2007@YourComputer:~$ date```

当我们在shell中输入一个命令时,shell会解析这个命令并执行它。这里,shell执行了一个名叫date的程序,输出当前的日期和时间。

1
2
tye2007@YourComputer:~$ echo hello
hello

在这个例子中,我们使用echo命令,并传递了一个参数hello,它会将参数打印到屏幕上。
shell基于空格分隔命令和参数,如果希望参数中包含空格,可以使用引号将其括起来:

1
2
tye2007@YourComputer:~$ echo "hello world"
hello world

或者你可以使用转义符号\来处理:

1
2
tye2007@YourComputer:~$ echo hello\ world
hello world

然而,shell要执行一个程序,必须知道它所在的位置。当接收到一个命令时,shell会区分两种情况:

  1. 内置命令:一些命令是shell自带的,比如cd(改变目录)和exit(退出shell)。这些命令不需要查找外部程序,shell直接执行它们。
  2. 外部命令:大多数命令都是外部程序,比如dateecho。shell需要在系统的特定目录中查找这些程序。

这里就涉及到一个重要的环境变量——PATHPATH变量包含了一系列目录,当你输入一个命令时,shell会按照PATH中列出的顺序依次在这些目录中查找对应的可执行文件。
你可以使用下面的命令来查看当前的PATH变量:

1
2
3
tye2007@YourComputer:~$ echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/
bin:/usr/games:/usr/local/games

每个目录之间用冒号(:)分隔。当你输入一个命令时,shell会从左到右依次检查这些目录,直到找到对应的可执行文件为止。
如果你想知道某个命令对应的可执行文件在哪里,可以使用which命令:

1
2
tye2007@YourComupter:~$ which date
/usr/bin/date

这表示date命令对应的可执行文件位于/usr/bin/目录下。

在shell中导航

shell中的路径是一组被分割的目录,在Linux和Unix系统中,路径使用斜杠(/)作为分隔符。例如,/home/tye2007/Documents表示Documents目录位于tye2007用户的主目录下,而tye2007目录又位于home目录下。
你可以使用pwd查看当前工作目录:

1
2
tye2007@YourComputer:~$ pwd
/home/tye2007

要改变当前工作目录,可以使用cd命令:

1
2
3
4
5
6
7
8
9
10
11
tye2007@YourComputer:~$ cd Documents
tye2007@YourComputer:~/Documents$ pwd
/home/tye2007/Documents
tye2007@YourComputer:~/Documents$ cd ..
tye2007@YourComputer:~$ pwd
/home/tye2007
tye2007@YourComputer:~$ cd ./Downloads
tye2007@YourComputer:~/Downloads$ pwd
/home/tye2007/Downloads
tye2007@YourComputer:~/Downloads$ ../../bin/echo "Back to bin"
Back to bin

在上面的例子中,cd Documents将当前目录切换到Documents目录下。cd ..命令将当前目录切换到上一级目录。cd ./Downloads命令将当前目录切换到Downloads目录下。..表示上一级目录,.表示当前目录。你也可以使用绝对路径来切换目录,比如cd /home/tye2007/Downloads

一般来说,我们运行一个程序时,如果没有指定路径,则该程序会在当前目录下执行。
为了查看指定目录下包含哪些文件,我们使用ls命令:

1
2
tye2007@YourComputer:~$ ls
Documents Downloads Music Pictures Videos

这个命令会列出当前目录下的所有文件和子目录。如果你想查看某个特定目录下的文件,可以在ls命令后面加上目录路径:

1
2
tye2007@YourComputer:~$ ls Documents
file1.txt file2.txt projects

这个命令会列出Documents目录下的所有文件和子目录。
大多数命令接受标记(flag)和选项(option)来修改其行为。标记通常以单个破折号(-)开头,而选项则以双破折号(–)开头。我们可以使用--help或者-h获取帮助信息,以了解有那些二可用的标记或选项。
ls -l可以详细地列出目录下文件或文件夹的信息,例如:

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
tye2007@YourComputer:/$ ls -l
total 2816
lrwxrwxrwx 1 root root 7 Apr 22 2024 bin -> usr/bin
drwxr-xr-x 2 root root 4096 Feb 26 2024 bin.usr-is-merged
drwxr-xr-x 2 root root 4096 Apr 22 2024 boot
drwxr-xr-x 15 root root 3860 Jan 8 12:54 dev
drwxr-xr-x 88 root root 4096 Jan 8 12:54 etc
drwxr-xr-x 3 root root 4096 Dec 26 17:49 home
-rwxr-xr-x 1 root root 2781568 Dec 12 09:58 init
lrwxrwxrwx 1 root root 7 Apr 22 2024 lib -> usr/lib
drwxr-xr-x 2 root root 4096 Apr 8 2024 lib.usr-is-merged
lrwxrwxrwx 1 root root 9 Apr 22 2024 lib64 -> usr/lib64
drwx------ 2 root root 16384 Dec 26 17:46 lost+found
drwxr-xr-x 2 root root 4096 Aug 6 00:55 media
drwxr-xr-x 6 root root 4096 Dec 26 17:47 mnt
drwxr-xr-x 2 root root 4096 Aug 6 00:55 opt
dr-xr-xr-x 329 root root 0 Jan 8 12:54 proc
drwx------ 4 root root 4096 Dec 28 23:24 root
drwxr-xr-x 20 root root 580 Jan 8 12:54 run
lrwxrwxrwx 1 root root 8 Apr 22 2024 sbin -> usr/sbin
drwxr-xr-x 2 root root 4096 Mar 31 2024 sbin.usr-is-merged
drwxr-xr-x 2 root root 4096 Dec 26 17:47 snap
drwxr-xr-x 2 root root 4096 Aug 6 00:55 srv
dr-xr-xr-x 13 root root 0 Jan 8 13:02 sys
drwxrwxrwt 8 root root 4096 Jan 8 13:03 tmp
drwxr-xr-x 12 root root 4096 Aug 6 00:55 usr
drwxr-xr-x 13 root root 4096 Dec 26 17:47 var
drwx------ 2 root root 4096 Jan 8 12:54 wslHJHjAO
drwx------ 2 root root 4096 Jan 8 12:54 wslLjIOiM
drwx------ 2 root root 4096 Jan 8 12:54 wslcAjDBO
drwx------ 2 root root 4096 Jan 8 12:54 wslobMdpN
drwx------ 2 root root 4096 Jan 8 12:54 wslpgLpAO

每行都包含当前文件夹下某一个文件或文件夹的具体信息。具体来讲,每一行的信息包括:

  • 文件类型和权限(如drwxr-xr-x表示这是一个目录,且具有读、写、执行权限)
  • 硬链接数(如2
  • 文件所有者(如root
  • 文件所属组(如root
  • 文件大小(如4096字节)
  • 最后修改时间或访问时间(如Apr 22 2024
  • 文件名(如bin

关于Linux的文件类型

在Linux系统中,文件有多种类型,常见的包括:

  • 普通文件(-):这是最常见的文件类型,包含纯文本文件、二进制文件、数据格式文件等。
  • 目录文件(directory):目录文件用于组织和存储其他文件和目录。
  • 符号链接文件(link):符号链接文件类似于Windows中的快捷方式,它指向另一个文件或目录。
  • 字符(character)设备或块(block)设备文件:这些文件用于表示硬件设备,如终端、打印机、磁盘等。
  • 数据接口文件(socket):这些文件用于进程间通信。通常在/var/run/目录下可以找到。
  • 命名管道文件(pipe):这些文件用于在进程间传输数据。

需要注意的是,Linux系统中的一切皆为文件,这意味着设备、目录、进程等都可以被视为文件进行操作。
同时,Linux系统的文件系统实际上并没有后缀名的概念,文件的类型通常通过文件内容和权限来确定,而不是通过文件名的后缀。即便一个文件具有特定的后缀名(如.txt.jpg等),这并不一定意味着它就是该类型的文件。而且,一个文件是否可执行,取决于其权限设置,而不是文件名后缀。文件名后缀的真正意义在于帮助用户识别文件的作用和使用方式。

关于Linux的权限系统

Linux系统采用基于用户和组的权限管理机制。每个文件和目录都有三个基本权限:读(r)、写(w)和执行(x)。这些权限分别对应于文件的所有者、所属组和其他用户。

  • 读权限(r):允许查看文件内容或列出目录内容。
  • 写权限(w):允许修改文件内容或在目录中创建、删除文件。
  • 执行权限(x):允许执行文件(如果是可执行文件)或进入目录。

权限通常以三组字符表示,每组三个字符,分别对应所有者、所属组和其他用户。例如,rwxr-xr--表示:

  • 所有者具有读、写和执行权限(rwx)
  • 所属组具有读和执行权限(r-x)
  • 其他用户仅具有读权限(r–)

对于目录,读取权限允许列出目录中包含的文件,写权限允许用户重命名、创建或删除目录中的文件,执行权限允许用户进入该目录。(非常重要!)
此外,Linux系统还支持特殊权限,如Setuid、Setgid和粘滞位,这些权限可以赋予文件或目录特定的行为。

其他指令

mv命令用于移动或重命名文件和目录,它接受两个参数:源文件(或目录)和目标文件(或目录)。例如:

1
tye2007@YourComputer:~$ mv oldname.txt newname.txt

这个命令将oldname.txt重命名为newname.txt。如果指定的目标是一个目录,则会将源文件移动到该目录下。

cp命令用于复制文件和目录。它也接受两个参数:源文件(或目录)和目标文件(或目录)。例如:

1
tye2007@YourCopmuter:~$ cp source.txt ../backup.txt

这个命令将source.txt复制到上一级目录,并命名为backup.txt

rm命令用于删除文件和目录。要删除一个文件,可以使用:

1
tye2007@YourComputer:~$ rm unwanted.txt

这个命令将删除unwanted.txt文件。因为这个命令默认不会递归地删除目录,要删除一个目录及其内容,可以使用-r标记:

1
tye2007@YourComputer:~$ rm -r old_directory

这个命令将递归地删除old_directory目录及其所有内容。请谨慎使用rm命令,因为删除的文件和目录通常无法恢复。

man命令用于查看命令的手册页,提供有关命令的详细信息和用法。例如:

1
tye2007@YourComputer:~$ man ls

这个命令将显示ls命令的手册页,包含其用法、选项和示例。一般用vim风格的界面浏览手册页,按q键退出。

rmdir用于删除空目录。例如:

1
tye2007@YourComputer:~$ rmdir empty_directory

这个命令将删除名为empty_directory的空目录。如果目录不为空,rmdir命令将无法删除它。

mkdir用于创建新目录。例如:

1
tye2007@YourComputer:~$ mkdir new_directory new_directory2

这个命令将创建两个新目录,分别命名为new_directorynew_directory2

Ctrl+C:中断当前正在运行的命令或程序,返回到提示符。
Ctrl+L:清除终端屏幕内容,相当于执行clear命令。
Tab键:自动补全命令或文件名。如果输入部分命令或文件名后按下Tab键,shell会尝试补全剩余部分。如果有多个可能的补全选项,按两次Tab键会显示所有选项。

在程序间创建连接:流

在shell中,程序有两个“流”:输入流和输出流。默认情况下,输入流是键盘,输出流是屏幕。我们可以使用重定向符号来改变这些流的来源和去向。

在此之前,我们需要了解一下cat命令,它用于连接文件并将其内容输出到标准输出(通常是屏幕)。例如:

1
2
3
4
5
6
7
8
tye2007@YourComputer:~$ cat file.txt
This is the content of file.txt.
It has multiple lines.
tye2007@YourComputer:~$ cat file1.txt file2.txt
This is the content of file1.txt.
It has multiple lines.
This is the content of file2.txt.
It also has multiple lines.

它的工作流程可以总结如下:

  1. 顺序读取指定的文件数据(如果有多个文件,则依次读取每个文件)。
  2. 将读取到的内容暂存在用户态缓冲区中。
  3. 将缓冲区中的内容输出到标准输出(通常是屏幕)。

>符号用于将程序的输出重定向到一个文件中。例如:

1
2
3
tye2007@YourComputer:~$ echo "Hello, World!" > hello.txt
tye2007@YourComputer:~$ cat hello.txt
Hello, World!

这个命令将echo命令的输出写入到hello.txt文件中。如果文件已经存在,使用>会覆盖原有内容。

<符号用于将文件的内容作为程序的输入。例如:

1
2
3
4
5
tye2007@YourComputer:~$ cat < hello.txt
Hello, World!
tye2007@YourComputer:~$ cat < hello.txt > hello2.txt
tye2007@YourComputer:~$ cat hello2.txt
Hello, World!

其中cat < hello.txthello.txt的内容作为cat命令的输入,并输出到屏幕上,它与cat hello.txt效果和原理并无差别。第二个命令将hello.txt的内容通过输入重定向传递给cat,然后通过输出重定向将结果写入到hello2.txt文件中。

>>符号用于将程序的输出追加到一个文件的末尾。例如:

1
2
3
4
tye2007@YourComputer:~$ echo "This is a new line." >> hello.txt
tye2007@YourComputer:~$ cat hello.txt
Hello, World!
This is a new line.

使用管道,我们能够更好地利用文件重定向。|符号用于将一个程序的输出直接传递给另一个程序作为输入。例如:

1
2
3
4
tye2007@YourComputer:~$ ls -l / | tail -n1
drwx------ 2 root root 4096 Jan 8 12:54 wslpgLpAO
tye2007@YourComputer:~$ curl --head --silent google.com | grep --ignore-case content-length | cut --delimiter ' ' -f2
219

在第一个例子中,ls -l /命令列出根目录下的所有文件和目录的详细信息,然后通过管道将输出传递给tail -n1命令,后者只显示最后一行结果。在第二个例子中,curl --head --silent google.com命令获取Google首页的HTTP头信息,并通过管道将输出传递给grep --ignore-case content-length命令,后者筛选出包含content-length的行,最后再通过管道将结果传递给cut --delimiter ' ' -f2命令,后者提取出第二个字段,即内容长度。
这样,我们就可以将多个命令组合起来,形成一个强大的数据处理流水线。

根用户

在Linux系统中,根用户(root)是系统的超级用户,拥有对系统的完全控制权限。根用户可以执行任何操作,包括修改系统文件、安装软件、管理用户等。由于根用户具有极高的权限,因此在日常使用中,建议尽量避免以根用户身份登录或执行命令,以防止意外修改或删除重要的系统文件。
要以根用户身份执行某个命令,可以使用sudo命令。但有一件事是只能作为根用户的执行的,那就是向sysf文件写入内容。系统被挂挂载在/sys目录下,sysf文件则暴露了一些内核参数。所以你无需任何特殊工具配置系统内核,而Windows和MacOS则没有这个文件。
例如,下面的命令将一个值写入/sys目录下的某个文件:

1
2
3
4
5
tye2007@YourComputer:~$ sudo find -L /sys/class/backlight/ -maxdepth 2 -name '*brightness*'
/sys/class/backlight/intel_backlight/brightness
tye2007@YourComputer:~$ sudo bash -c 'echo 1000 > /sys/class/backlight/intel_backlight/brightness'
An error occurred while redirecting file 'brightness'.
open: Permission denied

在这个例子中,sudo bash -c 'echo 1000 > /sys/class/backlight/intel_backlight/brightness'命令尝试将值1000写入brightness文件中。然而,由于重定向操作是在普通用户权限下执行的,因此会导致权限被拒绝的错误。为了解决这个问题,我们可以使用tee命令来实现:

1
2
tye2007@YourComputer:~$ echo 1000 | sudo tee /sys/class/backlight/intel_backlight/brightness
1000

总结

shell也是一种交互式编程环境。它的执行顺序也遵循REPL的模式:输入命令 → Shell 词法/语法处理 → 历史展开 (!) → 变量展开 ($) → 通配符展开 (*) → execve() → 程序运行。

补充命令

history expasion

历史展开允许你快速重复之前输入过的命令。历史展开在输入被读取之后立即进行,但在程序被执行之前进行。它接受两个部分:第一,是一个入口,指向历史列表中的某个命令;第二,是用于选择命令中的某个部分。

  • !!:重复执行上一个命令。例如:

    1
    2
    3
    4
    5
    tye2007@YourComputer:~$ echo "Hello, World!"
    Hello, World!
    tye2007@YourComputer:~$ !!
    echo "Hello, World!"
    Hello, World!
  • !n:重复执行历史列表中的第n个命令。例如:

    1
    2
    3
    4
    5
    6
    7
    8
    tye2007@YourComputer:~$ history
    1 echo "Hello, World!"
    2 ls -l
    3 pwd
    tye2007@YourComputer:~$ !2
    ls -l
    total 0
    -rw-r--r-- 1 tye2007 tye2007 0 Jan 8 13:30 file1.txt
  • !-n:重复执行倒数第n个命令。例如:

    1
    2
    3
    4
    5
    6
    7
    8
    tye2007@YourComputer:~$ history
    1 echo "Hello, World!"
    2 ls -l
    3 pwd
    tye2007@YourComputer:~$ !-2
    ls -l
    total 0
    -rw-r--r-- 1 tye2007 tye2007 0 Jan 8 13:30 file1.txt
  • !string:重复执行最近一个以string开头的命令。例如:

    1
    2
    3
    4
    5
    6
    7
    8
    tye2007@YourComputer:~$ history
    1 echo "Hello, World!"
    2 ls -l
    3 pwd
    tye2007@YourComputer:~$ !ls
    ls -l
    total 0
    -rw-r--r-- 1 tye2007 tye2007 0 Jan 8 13:30 file1.txt

关于!的unquoting

When using the shell, only ‘\’ and ‘’’ may be used to escape the history expansion character, but the history expansion character is also treated as quoted if it immediately precedes the closing double quote in a double-quoted string.
Several characters inhibit history expansion if found immediately following the history expansion character, even if it is unquoted: space, tab, newline, carriage return, ‘=’, and the other shell metacharacters.

也就是说,!只能被反斜杠\和单引号'转义。如果!紧跟在双引号的结尾处,它也会被视为已转义。此外,如果!后面紧跟空格、制表符、换行符、回车符、等号或其他shell元字符,它也不会触发历史展开。

grep命令

grep命令用于在文件或输入流中搜索指定的模式,并输出匹配的行。它支持正则表达式,可以进行复杂的文本搜索和处理。
例如,下面的命令在file.txt文件中搜索包含pattern的行:

1
2
3
tye2007@YourComputer:~$ grep 'pattern' file.txt
This is a line containing pattern.
Another line with pattern here.

这个命令会输出file.txt中所有包含pattern的行。你也可以使用管道将其他命令的输出传递给grep进行搜索:

1
2
3
tye2007@YourComputer:~$ ls -l | grep '^d'
drwxr-xr-x 2 root root 4096 Apr 22 2024 boot
drwxr-xr-x 3 root root 4096 Dec 26 17:49 home

这个命令会列出当前目录下所有的子目录(以d开头的行表示目录)。
grep命令还支持多种选项,例如:

  • -i:忽略大小写进行搜索。
  • -v:反转匹配,输出不包含指定模式的行。
  • -r:递归搜索目录中的文件。
  • -n:显示匹配行的行号。
  • -c:只输出匹配行的数量。
    例如:
1
2
3
4
5
6
7
8
9
10
tye2007@YourComputer:~$ grep -i 'pattern' file.txt
This is a line containing Pattern.
Another line with PATTERN here.
tye2007@YourComputer:~$ grep -v 'pattern' file.txt
This line does not contain the keyword.
tye2007@YourComputer:~$ grep -n 'pattern' file.txt
2:This is a line containing pattern.
4:Another line with pattern here.
tye2007@YourComputer:~$ grep -c 'pattern' file.txt
2

cut命令

cut命令用于从文本流或者文件中提取指定的列或字段。它可以根据分隔符将每一行分割成多个字段,然后选择需要的字段进行输出。

下面是一些常用的cut命令选项:

  • -b --bytes=LIST:按字节提取指定范围的内容。
  • -c --characters=LIST:按字符提取指定范围的内容。
  • -d --delimiter=DELIM:使用指定分隔符分割字段。
  • -f --fields=LIST:提取指定的字段,字段编号从1开始。
  • -n :与-b选项一起使用,防止切割多字节字符。
    • --complement:提取未指定的字段。
  • -s --only-delimited:仅输出包含分隔符的行。
    • --output-delimiter=STRING:指定输出字段之间的分隔符。

在选取分割好的字段时,必须且只能选取-b-c-f中的一个,不能混用。
这之后,可以使用逗号分隔的列表来指定要提取的字段,或者使用连字符指定一个范围。例如:

1
2
3
4
5
6
7
8
9
10
tye2007@YourComputer:~$ echo "apple,banana,cherry,date" | cut -d ',' -f 2
banana
tye2007@YourComputer:~$ echo "apple,banana,cherry,date" | cut -d ',' -f 2-3
banana,cherry
tye2007@YourComputer:~$ echo "apple,banana,cherry,date" | cut -d ',' -f -2
apple,banana
tye2007@YourComputer:~$ echo "apple,banana,cherry,date" | cut -d ',' -f 3-
cherry,date
tye2007@YourComputer:~$ echo "apple,banana,cherry,date" | cut -d ',' -f 1,4
apple,date

在这些例子中,cut命令使用逗号作为分隔符,并提取了指定的字段。第一个命令提取了第二个字段banana,第二个命令提取了第二和第三个字段banana,cherry,依此类推。

curl命令

curl命令是一个用于在命令行下进行数据传输的工具,支持多种协议,包括HTTP、HTTPS、FTP等。它可以用来发送请求、下载文件、上传数据等。

下面是一些常用的curl命令选项:

  • -o --output <file>:将下载的内容保存到指定的文件中。
  • -O –remote-name`:使用远程文件的名称保存下载的内容。
  • -L --location:跟随重定向。
  • -I --head:仅获取HTTP头信息。
  • -d --data <data>:发送POST请求时附加数据。
  • -H --header <header>:添加自定义HTTP头。
  • -X --request <command>:指定请求方法,如GET、POST
  • --silent:静默模式,不显示进度条和错误信息。
  • --user <user:password>:使用指定的用户名和密码进行身份验证。
  • --cookie <data|filename>:发送Cookie数据或从文件中读取Cookie。

例如,下面的命令使用curl下载一个网页并将其保存到本地文件中:

1
2
tye2007@YourComputer:~$ curl -o example.html https://www.example.com
tye2007@YourComputer:~$ curl -L -o example.html https://www.example.com

这个命令将https://www.example.com网页的内容下载并保存到example.html文件中。如果网页发生重定向,-L选项会使curl跟随重定向。

你也可以使用curl发送POST请求并附加数据:

1
tye2007@YourComputer:~$ curl -X POST -d "param1=value1&param2=value2" https://www.example.com/api

这个命令向https://www.example.com/api发送一个POST请求,并附加了两个参数param1param2
此外,curl还可以与其他命令结合使用,通过管道处理数据。例如:

1
2
tye2007@YourComputer:~$ curl --head --silent https://www.example.com | grep --ignore-case content-type
Content-Type: text/html; charset=UTF-8

这个命令获取https://www.example.com的HTTP头信息,并通过管道将输出传递给grep命令,筛选出包含content-type的行。

find命令

find命令用于在文件系统中搜索文件和目录。它可以根据各种条件(如名称、类型、大小、修改时间等)来查找文件,并对找到的文件执行指定的操作。

下面是一些常用的find命令选项:

  • -name <pattern>:按名称搜索文件,支持通配符。
  • -type <type>:按文件类型搜索文件,如f表示普通文件,d表示目录。
  • -size <n>:按文件大小搜索文件,如+n表示文件大小大于n字节,-n表示小于n字节。
  • -mtime <n>:按修改时间搜索文件,如+n表示n天前修改的文件,-n表示n天内修改的文件。
  • -exec <command> {} \;:对找到的每个文件执行指定的命令,{}表示当前文件。
  • -maxdepth <n>:限制搜索的目录深度为n级。
  • -print:打印找到的文件路径(默认行为)。
  • -delete:删除找到的文件。
  • -user <username>:按文件所有者搜索文件。
  • -group <groupname>:按文件所属组搜索文件。
  • -perm <mode>:按文件权限搜索文件。
  • -empty:查找空文件或空目录。
  • -newer <file>:查找比指定文件更新的文件。
  • -ctime <n>:按创建时间搜索文件,如+n表示n天前创建的文件,-n表示n天内创建的文件。
  • -atime <n>:按访问时间搜索文件,如+n表示n天前访问的文件,-n表示n天内访问的文件。
  • -regex <pattern>:按正则表达式搜索文件路径。
  • -L:跟随符号链接进行搜索。
  • -H:在命令行参数中跟随符号链接进行搜索。
  • -P:不跟随符号链接进行搜索(默认行为)。

例如,下面的命令在当前目录及其子目录中搜索名为example.txt的文件:

1
2
tye2007@YourComputer:~$ find . -name 'example.txt'
./Documents/example.txt

这个命令会在当前目录(.)及其子目录中查找名为example.txt的文件,并打印出其路径。

课后习题

Q1

在 /tmp 下新建一个名为 missing 的文件夹。

Q2

用 man 查看程序 touch 的使用手册。

Q3

用 touch 在 missing 文件夹中新建一个叫 semester 的文件。

Q4

将以下内容一行一行地写入 semester 文件:

1
2
#!/bin/sh
curl --head --silent https://missing.csail.mit.edu

Q5

尝试执行这个文件。例如,将该脚本的路径(./semester)输入到您的 shell 中并回车。如果程序无法执行,请使用 ls 命令来获取信息并理解其不能执行的原因。

Q6

查看 chmod 的手册(例如,使用 man chmod 命令)

Q7

使用 chmod 命令改变权限,使 ./semester 能够成功执行,不要使用 sh semester 来执行该程序。

Q8

使用 | 和 > ,将 semester 文件输出的最后更改日期信息,写入主目录下的 last-modified.txt 的文件中

Q9

写一段命令来从 /sys 中获取笔记本的电量信息,或者台式机 CPU 的温度。注意:macOS 并没有 sysfs,所以 Mac 用户可以跳过这一题。

A1

1
tye2007@YourComputer:~$ mkdir /tmp/missing

A2

1
tye2007@YourComputer:~$ man touch

A3

1
tye2007@YourComputer:~$ touch /tmp/missing/semester

A4

1
2
tye2007@YourComputer:~$ echo '#!/bin/sh' >> /tmp/missing/semester
tye2007@YourComputer:~$ echo 'curl --head --silent https://missing.csail.mit.edu' >> /tmp/missing/semester

注意:这里只能使用单引号或者反斜杠,否则#可能被解释为注释,或者!被解释为历史展开。

A5

1
2
3
4
tye2007@YourComputer:~$ /tmp/missing/semester
bash: /tmp/missing/semester: Permission denied
tye2007@YourComputer:~$ ls -l /tmp/missing/semester
-rw-r--r-- 1 tye2007 tye2007 64 Jan 8 13:45 /tmp/missing/semester

A6

1
tye2007@YourComputer:~$ man chmod

A7

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
tye2007@YourComputer:~$ chmod +x /tmp/missing/semester
tye2007@YourComputer:~$ /tmp/missing/semester
HTTP/1.1 200 OK
Date: Mon, 08 Jan 2024 05:45:00 GMT
Content-Type: text/html; charset=UTF-8
Connection: keep-aliveHTTP/1.1 200 Connection established

HTTP/2 200
server: GitHub.com
content-type: text/html; charset=utf-8
last-modified: Wed, 07 Jan 2026 15:52:03 GMT
access-control-allow-origin: *
etag: "695e8123-2354"
expires: Thu, 08 Jan 2026 15:37:31 GMT
cache-control: max-age=600
x-proxy-cache: MISS
x-github-request-id: 2548:8F4F4:2CD093:2DFC83:695FCCE0
accept-ranges: bytes
age: 240
date: Thu, 08 Jan 2026 15:31:32 GMT
via: 1.1 varnish
x-served-by: cache-lax-kwhp1940024-LAX
x-cache: HIT
x-cache-hits: 0
x-timer: S1767886292.203566,VS0,VE1
vary: Accept-Encoding
x-fastly-request-id: 2093d342ee0c5763043c76ecf7cb37a159b3ef60
content-length: 9044

A8

1
tye2007@YourComputer:~$ /tmp/missing/semester | grep --ignore-case 'last-modified' > ~/last-modified.txt

A9

1
2
tye2007@YourComputer:~$ cat /sys/class/power_supply/BAT0/capacity
85

参考链接:shell