基本的 bash shell 命令

启动 shell

大多数 Linux 默认的 shell 是 GNU bash shell,当然还有其他 shell,我们可以查看系统当前可用的 shell:

$ cat /etc/shells
# /etc/shells: valid login shells
/bin/sh
/bin/bash
/bin/rbash
/bin/dash
/usr/bin/screen

查看默认的 shell:

$ echo $SHELL
/bin/bash

查看每个用户默认的 shell(最后一个字段):

$ cat /etc/passwd
root:x:0:0:root:/root:/bin/bash

shell 提示符

进入终端后,就会看到 shell CLI 提示符,这就是我们输入命令的地方。默认的 bash shell 提示符是 $,表示等待用户输入。

提示符可能包含其他信息,比如在 Ubuntu 上,提示符还会显示当前用户ID,系统名等内容。

pi@raspbian:~$

bash 手册

可以用 man 命令(manual)来访问存储在 Linux 上的手册页面。在想要查找的工具的名称前面输入 man 命令,就能找到那个工具相应的手册条目。比如,想要了解 bash 的信息,可以输入 man bash,就能看到如下页面:

man bash

可以用回车来逐行查看,或用空格来翻页查看,有些终端也支持用鼠标滚轮滚动查看。看完后按 q 退出。

手册将命令分成不同的节,常用的节如下:

描述
Name 显示命令名和一段简短的描述
Synopsis 命令的语法
Configuration 命令配置信息
Description 命令的一般性描述
Options 命令选项描述
Environment 描述所使用的环境变量

如果不记得命令名,可以用关键字搜索手册,语法是:man -k 关键字

浏览文件系统

在 Windows 中,每个磁盘对应一个盘符,文件路径以一个盘符开头。

而在 Linux 中,所有文件都存储在一个虚拟目录(virtual directory)结构中,该结构以根(root)目录开头,根目录下的目录和文件会按照访问它们的目录路径一一列出(与 Windows 类似)。比如:

/home/pi/code/python/

Linux 路径本身并没有提供任何关于文件存在哪个物理磁盘上的信息。在 Linux PC 上安装的第一块硬盘称为根驱动器,根驱动器包含虚拟目录的核心。如果安装其他磁盘,Linux 会在根驱动器上创建一些特别的目录,称为挂载点(mount point),挂载点中的文件和目录存储在其他磁盘中。

一般来说,系统文件存在根驱动器中,用户文件存在其他驱动器。(就像 Windows 的 C: 盘和 D: 盘)

常见的 Linux 目录名称有:

目录 用途
/ 根目录,通常不会在这里存储文件
/bin 二进制目录,存放用户级 GNU 工具
/boot 启动目录,存放启动文件
/dev 设备目录,Linux 在这里创建设备节点
/home 主目录,Linux 在这里创建用户目录
/lib 库目录,存放系统和应用程序的库文件
/media 媒体目录,可移动媒体设备的挂载点
/mnt 挂载目录,另一个可移动媒体设备的挂载点
/opt 可选目录,常用于存放第三方软件包和数据文件
/proc 进程目录,存放现有硬件及当前进程的相关信息
/root root用户的主目录
/sbin 系统二进制目录,存放 GNU 管理员级工具
/run 存放系统运行时的运行时数据
/srv 服务目录,存放本地服务的相关文件
/sys 系统目录,存放系统硬件信息的相关文件
/tmp 临时目录,存放临时文件
/usr 用户二进制目录,存放用户级 GNU 工具
/var 可变目录,存放经常发生变化的文件,比如日志文件

常见的目录名是基于文件系统层级标准(filesystem hierarchy standard, FHS),很多 Linux 发行版都遵循了 FHS。我们可以在 https://www.pathname.com/fhs/ 查看最新 FHS 标准。

当登录到 CLI 后,会话将从主目录开始,主目录是分配给用户账户的一个特有目录。

遍历目录

可以使用 cd 目录将 shell 会话切换到另一个目录,格式为:cd 目录

目录可以用绝对路径或相对路径表示。

  • 绝对文件路径:从根目录开始,即以 / 开头
  • 相对文件路径:从当前位置开始

波浪号 ~ 表示用户的主目录,我们可以用它来简化路径。比如 cd ~ 表示回到主目录,或者直接输入 cd 也能回到主目录。

如果不知道当前位置,可以用 pwd 来查看。

有两个特殊字符可以用在相对文件路径中:

  • .:表示当前目录
  • ..:表示当前目录的父目录

可以用多个 .. 来向上切换目录。比如说 cd ../../ 表示回到上两级目录。

文件和目录列表

可以用 ls 查看当前目录下的文件和目录:

$ cd /
$ ls
bin   dev  home  lost+found  mnt  proc  run   srv       sys  usr
boot  etc  lib   media       opt  root  sbin  swapfile  tmp  var

可以用 ls 目录 来查看特定目录下的文件和目录。

$ ls /
bin   dev  home  lost+found  mnt  proc  run   srv       sys  usr
boot  etc  lib   media       opt  root  sbin  swapfile  tmp  var

如果是彩色终端,ls命令还可以用不同颜色来区分不同类型的文件。如果没安装彩色终端,可以用 ls -F 来区分文件和目录:

$ ls -F /
bin/   dev/  home/  lost+found/  mnt/  proc/  run/   srv/      sys/  usr/
boot/  etc/  lib/   media/       opt/  root/  sbin/  swapfile  tmp/  var/

ls命令会隐藏以 . 开头的文件,要显示隐藏文件,可以用 ls -a

$ ls -a
.   .aspnet        .bash_logout  .cache  .config  .local    .python_history
..  .bash_history  .bashrc       code    .gnupg   .profile  .Xauthority

如果想要递归显示子目录下的文件,可以用 ls -R

$ ls -R
.:
jellyfin  vscode-cpptools

./jellyfin:

./vscode-cpptools:
ipch

如果想显示详细信息,可以用 ls -l

$ ls -l
total 1048660
drwxr-xr-x   2 root root       4096 Jan  2 23:47 bin
drwxr-xr-x   5 root root      16384 Jan  1  1970 boot
drwxr-xr-x  17 root root       3660 Feb  2 18:07 dev
drwxr-xr-x 113 root root       4096 Jan 20 17:33 etc
drwxr-xr-x   3 root root       4096 Jan  2 22:35 home

每一行包括下述信息:

  • 文件类型,比如目录(d)、文件(-)、字符型文件(c)或块设备(b)
  • 文件的权限
  • 文件的硬链接总数
  • 文件属主的用户名
  • 文件属组的组名
  • 文件的大小(byte)
  • 文件的上次修改时间
  • 文件名或目录名

如果只想查找特定文件,可以用以下几种通配符:

  • ? 代表一个字符
  • * 代表零个或多个字符
  • [ai] 代表从中括号中选择一个字符
  • [a-i] 从 a 到 i 中选择一个字符
  • [!a] 排除 a

处理文件

创建文件

touch 创建空文件,如果文件已经存在,就会改变文件的修改时间。

$ touch test
$ ls
test

复制文件

复制文件可以用 cp,语法如下:

cp source destination

如果 source 和 destination 都是文件名,则把源文件复制成一个新文件,并以 destination 命名。如果目标文件已存在,则默认会覆盖,想要不覆盖,可以加上 -i 选项。

如果 destination 是目录,则会复制到目录下。为了区分目录名与文件名,要求目录名要以斜杠 / 结尾。如果想要将某个文件复制到当前目录,可以用单点符 .来表示当前目录:

$ cp test .

也可以用前面说的通配符,把符合条件的文件复制到目录下:

$ cp *scripts mod_scripts/

如果想要复制一个目录,就需要用到 -R 参数,表示递归复制整个目录的内容,比如:

$ cp -R source/ destination/

表示将 source 目录中的内容复制到 destination 中。

自动补全

在输入文件名输入到一半时,可以按以下 Tab 键,就会自动补全整个文件名。此外,自动补全也可以用于补全命令。

链接文件

要维护同一文件的多份副本,可以给一个物理文件创建多个虚拟副本,这种副本称为 链接。链接有两种:

  • 软链接(符号链接)
  • 硬链接

关于这两个的区别,可以去看知乎

软链接就是一个真实的文件,它有自己的大小、权限等等,但它指向的是另一个文件。我们可以用 ln -s 创建软链接:

$ ls -l test
-rw-r--r-- 1 pi sudo 27 Feb  5 21:40 test
$ ln -s test sl_test
$ ls -l *test
lrwxrwxrwx 1 pi sudo  4 Feb  5 21:40 sl_test -> test
-rw-r--r-- 1 pi sudo 27 Feb  5 21:40 test

注意到软连接和源文件的权限、大小都不同(大小是 sudo 后面那个数),另外,软链接的 inode 编号(用于标识文件和目录的编号)与源文件不同。我们可以用 ls -i 查看 inode 编号:

$ ls -i *test
18254 sl_test
18253 test

硬链接则相反,它是一个虚拟的文件,它的信息和源文件是一样的。可以用 ln 创建硬链接:

$ ls -il *test
18253 -rw-r--r-- 1 pi sudo 27 Feb  5 21:40 test
$ ln test hl_test
$ ls -il *test
18253 -rw-r--r-- 2 pi sudo 27 Feb  5 21:40 hl_test
18253 -rw-r--r-- 2 pi sudo 27 Feb  5 21:40 test

注意到两个文件的 inode 编号是一样的,并且大小、权限是一样的。

另外注意一下 pi 前面那个数字,指的是某个文件的硬链接数+1,所以当建立了硬链接后,就从 1 变成了 2.

那么什么时候硬,什么时候软呢?👉👌 我们有如下原则:

  • 如果想在不同存储媒体之间建立链接,则只能用软链接。
  • 不要创建软链接的软链接,这会造成混乱。

重命名与移动

mv 可以完成重命名与移动文件/目录,它的用法如下:

$ mv source destination

mv 会把 source 移到 destination 并重命名为 destination,但 inode 编号和时间戳保持不变。与 cp 类似,我们可以加上 -i 参数,避免覆盖已有文件。

删除

可以用 rm 来删除文件,建议加上 -i,这样删除前,shell 会确认是否会删除,防止误删。

如果要删除非空目录,需要加上 -r,即递归删除。

处理目录

创建目录

mkdir dir_name 可以创建一个名为 dir_name 的目录。

如果想要创建多级目录,需要用 mkdir -p new_dir/sub_dir/under_dir

删除目录

对于空目录,可以用 rmdirrm

对于非空目录,可以用 rm -r

查看文件内容

查看类型:file file_name

查看文本文件:如果是比较短的文件,就用 cat,如果是比较长的文件,可以用 moreless

查看文件的开头或结尾:headtail