shell修炼手册

csdiy实验

shell的学习其实是有些反人类的,这意味着你对着的界面是单调的黑屏一行行的代码。图形化时代一去不复返。但是同时它也是炫酷的,可以让你的工作效率大幅度增加。学习过程中作者感到有些痛苦,因为shell作为一个工具型脚本语言,并没有很具体的教程。csdiy上推荐的MIT教程应该是最好的了,推荐食用。附上链接。这篇文章中我会对我学到的知识,以关键词的分类方式进行总结(这样比较系统方便查找记忆),对课上的知识点进行实际运用。

什么是Shell?

shell其实是一种脚本语言,什么是脚本语言?它又与编译语言进行区分。

我们知道有的编程语言,如c/c++,必须在程序运行前将代码翻译成二进制形式,也就是生成可执行文件。

这个过程叫做编译,这样的编程语言叫做编译语言。

而有的编程语言,如 Shell、JavaScript、Python、PHP等,需要一边执行一边翻译,不会生成任何可执行文件,用户必须拿到源码才能运行程序。程序运行后会即时翻译,翻译完一部分执行一部分,不用等到所有代码都翻译完。

这个过程叫做解释。这样的语言叫做解释型语言或脚本语言。

这是它的定义,那它到底能干什么?引用MIT的话说

如今的计算机有着多种多样的交互接口让我们可以进行指令的的输入,从炫酷的图像用户界面(GUI),语音输入甚至是 AR/VR 都已经无处不在。 这些交互接口可以覆盖 80% 的使用场景,但是它们也从根本上限制了您的操作方式——你不能点击一个不存在的按钮或者是用语音输入一个还没有被录入的指令。 为了充分利用计算机的能力,我们不得不回到最根本的方式,使用文字接口:Shell

如何配置shell?

前人所述备矣,这里附上作者学长的博客文章,供大家参考。

进入正题!

课前提醒!

1.请确保你的环境是正确的(推荐wsl2)

  1. 本课程需要使用类 Unix shell,例如 Bash 或 ZSH。如果您在 Linux 或者 MacOS 上面完成本课程的练习,则不需要做任何特殊的操作。如果您使用的是 Windows,则您不应该使用 cmd 或是 Powershell;您可以使用 Windows Subsystem for Linux 或者是 Linux 虚拟机。使用 echo $SHELL 命令可以查看您的 shell 是否满足要求。如果打印结果为 /bin/bash/usr/bin/zsh 则是可以的。

2.请在你的home中进行学习测试,在其他地方你的权限有限,如果自己添加权限可能会导致权力过大的滥用(总之就是不安全)。运行以下代码即可

1
cd ~

echo && cat

1.echo其实类似c的printf。

1
2
wjy06@wjy:~$ echo "hello word"
hello word

2.那么对应c的&,在shell中则是$。(解决了作者对键盘上为什么要出现美元符号的困扰)

1
2
3
wjy06@wjy:~$ name="jade"
wjy06@wjy:~$ echo "My name is $name"
My name is jade

3.我们知道c中会解析转义字符,但是echo默认不会解析

1
2
wjy06@wjy:~$ echo "Line 1\nLine 2"
Line 1\nLine 2

4.当然如果你想用转义字符比如‘\n’进行换行也是可以的(-e)后面会展开讲解

1
2
3
wjy06@wjy:~$ echo -e "Line 1\nLine 2"
Line 1
Line 2

5.我们知道echo不会解析转义字符,但这不意味着它不会解析特殊字符,比如上面用到的“$”,那我们不想特定字符被解析时如何避免呢?

在Shell中,echo命令使用 单引号(' 时,会 禁用所有特殊字符的解释,包括变量、转义字符和通配符(如 $*、``等)

1
2
wjy06@wjy:~$ echo 'Hello, $USER! Today is $(date)'
Hello, $USER! Today is $(date)

6.echo还可以和重定向一起使用

在shell中,程序有两个主要的流,输入流和输出流。通常,程序的输入流输出流都是我们的终端。键盘作为输入,显示器作为输出。但是我们可以重定向这些流

最简单的重定向是 < file> file。这两个命令可以将程序的输入输出流分别重定向到文件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
missing:~$ echo hello > hello.txt 
#创建文件并写入内容
#echo hello:输出字符串 hello到标准输出(屏幕)> hello.txt:将标准输出重定向到文件 hello.txt(覆盖写入)
missing:~$ cat hello.txt
hello
#cat:直接读取文件内容并输出
missing:~$ cat < hello.txt
hello
#< hello.txt:将文件 hello.txt的内容作为 cat的输入
missing:~$ cat < hello.txt > hello2.txt
missing:~$ cat hello2.txt
hello
#通过重定向复制文件
#< hello.txt:将 hello.txt内容作为 cat的输入
#> hello2.txt:将 cat的输出重定向到 hello2.txt
#结果:创建 hello2.txt,内容与 hello.txt相同(相当于文件复制)

7.echo追加写入

上面提到的 “>”是覆盖写入,也就是说前面写的内容会被覆盖。当然我们也可以选择追加写入。

1
2
3
4
echo world >> hello.txt  # 追加内容
cat hello.txt
hello
world

8.重定向与管道符’|‘

使用管道( pipes ),我们能够更好的利用文件重定向。 | 操作符允许我们将一个程序的输出和另外一个程序的输入连接起来:

1
cat < hello.txt | grep "hello" > filtered.txt
  • “< hello.txt”: 将hello.txt的内容作为cat命令的输入(其实和cat hello.txt等效,但更明确的表达数据流向
  • “| grep “hello””: 管道符将cat的输出作为grep(后续将有讲解)命令的输入,grep “hello”起到字符串筛选的作用,从输入中筛选包含字符串“hello”的行。
  • “>filtered.txt”: 将grep的输出重定向到文件filetered.txt(覆盖写入)

让我们来实例演示以下

1
2
3
4
5
6
7
8
9
echo "hello world" >hello.txt
echo "goodbye world" >> hello .txt
#hello.txt内容
#hello world
#goodbye world
cat < hello.txt | grep "hello" >filtered.txt
cat filtered.txt
#输出hello world
# 只有包含 "hello" 的行被保留

cd && pwd &&ls

1.cd(Change Directory)

是 Linux/Unix 和 Windows 命令行中最基础且最常用的命令之一,用于切换当前工作目录。在路径中,. 表示的是当前目录

  • 切换到绝对路径(以/开头)

    1
    cd /usr/local/bin # 从根目录开始的完整路径
  • 切换到相对路径

    1
    cd document/project #相对于当前目录
  • 返回上一级目录

    1
    cd ..
  • 返回home目录

    1
    cd ~
  • 切换到上次所在目录

    1
    cd -
  • 搭配*号使用

    1
    cd /usr/local/*/bin  # 匹配local文件夹中第一个子文件夹有bin的目录

2.pwd(Print Working Directory),用于显示当前工作目录

它可以打印当前所在的绝对路径(也许你cd到一个文件夹里但是不确定是不是你要找的那个,这时候pwd可以派上用场)

当我在Home环境时

1
2
wjy06@wjy:~$ pwd
/home/wjy06

注意,pwd其实默认的是pwd -L,我们还可以选择pwd -P

-L(默认) 显示逻辑路径(包含符号链接的路径)
-P 显示物理路径(解析所有符号链接的真实路径)

插一嘴,那么你怎么知道它有哪些可选择的参数呢?(help的使用)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
wjy06@wjy:~$ pwd --help
pwd: pwd [-LP]
Print the name of the current working directory.

Options:
-L print the value of $PWD if it names the current working
directory
-P print the physical directory, without any symbolic links

By default, `pwd' behaves as if `-L' were specified.

Exit Status:
Returns 0 unless an invalid option is given or the current directory
cannot be read.

3.ls(List Directory Contents):列出当前目录下的文件和子目录

当我在根目录时

1
2
3
wjy06@wjy:/$ ls
bin boot etc init lib.usr-is-merged lost+found mnt proc run sbin.usr-is-merged srv tmp var
bin.usr-is-merged dev home lib lib64 media opt root sbin snap sys usr

可以看到是对应的

image-20250928104213117

当然,ls也有着许多参数供你选择。

选项 说明
-l 以长格式(详细信息)显示
-a 显示所有文件(包括隐藏文件 .file
-h 以人类可读的格式显示文件大小(如 KB、MB)
-t 按修改时间排序(最新修改的在前)
-r 反向排序
-R 递归列出子目录内容
--color 彩色显示(默认启用)

🛑注意! 不要轻易尝试 ls -r。如果停不下来了请按ctrl+c(当然挺炫酷的)

这些参数同样可以通过 ls --help获得。当然还有一个更全面的文档。那就是man,比如:

man ls

它会接受一个程序名作为参数,然后将它的文档(用户手册)展现给您。注意,使用 q 可以退出该程序

mkdir && touch

1.mkdir是 Linux 和类 Unix 系统中用于创建目录(文件夹)的基础命令,其名称源于 “make directory”。

它的操作很简单,如果你想在当前目录创建文件夹

1
mkdir my_folder

如果你想在某个特定路径创建目录,可以使用

1
mkdir /tmp/missing

当然它还有许多扩展应用来满足更复杂的需求

选项 说明 示例
-p 递归创建目录:如果路径中的父目录不存在,系统会自动创建它们。这在需要创建多层嵌套目录时特别有用。 mkdir -p project/docs/images会一次性创建 projectproject/docsproject/docs/images多级目录。
-m 设置目录权限:在创建目录时直接指定其访问权限,而无需事后使用 chmod命令修改。 mkdir -m 755 secure_dir会创建一个所有者拥有读、写、执行权限,其他用户拥有读和执行权限的目录。权限模式通常用八进制数表示(如 755, 644)。
-v 显示操作详情:让命令输出它正在执行的操作信息,对于脚本调试或确认操作结果很有帮助。 mkdir -v new_dir可能会输出 mkdir: created directory 'new_dir'

2.touch是 Linux 和类 Unix 系统中一个非常实用的命令行工具,主要功能是创建空文件和更新文件的时间戳

touch命令最直接的用途是快速创建一个或多个文件,

创建单个文件

1
touch filename.txt

创建多个文件(允许不同类型)

1
touch file1.txt file2.txt file3.md
⏰ 核心功能:管理文件时间戳

文件在 Linux 系统中通常包含三种时间属性(可使用 stat命令查看)

  • 访问时间 (Access Time, atime):文件最后一次被读取的时间。
  • 修改时间 (Modification Time, mtime):文件内容最后一次被修改的时间。
  • 变更时间 (Change Time, ctime):文件元数据(如权限、所有者)最后一次被改变的时间。touch命令默认影响的是 atimemtime

通过不同的选项,可以精确控制要更新的时间:

选项 作用
-a 只更新文件的访问时间
-m 只更新文件的修改时间
(无选项) 同时更新文件的访问和修改时间(此为默认行为)。