命令历史

命令行历史

!NUM 调用历史命令中的第 NUM 条命令
!string 调用历史命令中最近一条以 string 开头的命令
!?string 重复前一个包含 string 的命令
!! 执行上一条命令
!string:p 仅打印命令历史而不执行
!$:p 打印输出 !$ (上一条命令的最后一个参数) 的内容
!*:p 打印输出 !* (上一条命令的所有参数) 的内容
^string 删除上一条命令的第一个 string
^string1^string2 将上一条命令中的第一个 string1 替换成 string2
!:gs/string1/string2 将上一条命令中的所有 string1 替换为 string2
!$ 调用前一个命令中的最后一个参数
ctrl + r 在命令历史中搜索命令
ctrl + g 从历史搜索中退出
  1. ## !NUM 调用历史命令中的第 NUM 条命令
  2. [root@gkdaxue ~]# history 2
  3. 123 pwd
  4. 124 history 2
  5. [root@gkdaxue ~]# !123
  6. pwd
  7. /root
  8. ## !STRING : 调用历史命令中最近一条以 STRING 开头的命令
  9. [root@gkdaxue ~]# history 2
  10. 127 pwd
  11. 128 history 2
  12. [root@gkdaxue ~]# !pw
  13. pwd
  14. /root
  15. ## !! :执行上一条命令
  16. [root@gkdaxue ~]# pwd
  17. /root
  18. [root@gkdaxue ~]# !!
  19. pwd
  20. /root
  21. ## !$:p 打印输出 !$ (上一条命令的最后一个参数)的内容
  22. [root@localhost ~]# cat /etc/sysconfig/network-scripts/ifcfg-eno16777736
  23. [root@localhost ~]# !$:p
  24. /etc/sysconfig/network-scripts/ifcfg-eno16777736
  25. ## !*:p
  26. [root@localhost ~]# echo 111 222
  27. 111 222
  28. [root@localhost ~]# !*:p
  29. 111 222
  30. ## ^string 删除上一条命令的第一个 string
  31. [root@localhost ~]# echo 111 111 222
  32. 111 111 222
  33. [root@localhost ~]# ^111
  34. echo 111 222
  35. 111 222
  36. ## ^string1^string2 : 将上一条命令中的第一个 string1 替换成 string2
  37. [root@localhost ~]# echo 111 111 222
  38. 111 111 222
  39. [root@localhost ~]# ^111^222
  40. echo 222 111 222
  41. 222 111 222
  42. ## !:gs/string1/string2 :将上一条命令中的所有 string1 替换为 string2
  43. [root@localhost ~]# echo 111 111 111
  44. 111 111 111
  45. [root@localhost ~]# !:gs/111/222
  46. echo 222 222 222
  47. 222 222 222
  48. ## !$ : 调用前一个命令中的最后一个参数
  49. [root@localhost ~]# echo 111 222 333
  50. 111 222 333
  51. [root@localhost ~]# echo !$
  52. echo 333
  53. 333

调用历史参数

command !^ 调用上一个命令的第一个参数作为 cmd 的参数
command !$ 调用上一个命令的最后一个参数作为 cmd 的参数
command !* 调用上一个命令的全部参数作为 cmd 的参数
command !:n 调用上一个命令的第 n 个参数作为 cmd 的参数
command !n:^ 调用第 n 条命令的第一个参数
command !n:$ 调用第 n 条命令的最后一个参数
command !n:m 调用第 n 条命令的第 m 个参数
command !n:* 调用第 n 条命令的所有参数
  1. [root@localhost ~]# echo aaa bbb ccc ddd
  2. aaa bbb ccc ddd
  3. [root@localhost ~]# echo !^
  4. echo aaa
  5. aaa
  6. [root@localhost ~]# echo aaa bbb ccc ddd
  7. aaa bbb ccc ddd
  8. [root@localhost ~]# echo !$
  9. echo ddd
  10. ddd
  11. [root@localhost ~]# echo aaa bbb ccc ddd
  12. aaa bbb ccc ddd
  13. [root@localhost ~]# echo !*
  14. echo aaa bbb ccc ddd
  15. aaa bbb ccc ddd
  16. [root@localhost ~]# echo aaa bbb ccc ddd
  17. aaa bbb ccc ddd
  18. [root@localhost ~]# echo !:3
  19. echo ccc
  20. ccc
  21. [root@localhost ~]# history
  22. ...
  23. 575 echo aaa bbb ccc ddd
  24. [root@localhost ~]# echo !575:^
  25. echo aaa
  26. aaa
  27. [root@localhost ~]# echo !575:$
  28. echo ddd
  29. ddd
  30. [root@localhost ~]# echo !575:3
  31. echo ccc
  32. ccc
  33. [root@localhost ~]# echo !575:*
  34. echo aaa bbb ccc ddd
  35. aaa bbb ccc ddd

命令补全( Tab 键 )

直接补全 : 用户给定的字符串只有一条唯一对应的命令 给出列表 : 以用户给定的字符串为开头对应的命令不唯一,再次按 Tab 键则会给出列表

  1. ## 比如我想输入 echo 命令
  2. [root@localhost ~]# ech ## 然后直接按 Tab 键, 自动变为如下
  3. [root@localhost ~]# echo
  4. ## 给出列表
  5. [root@localhost ~]# pw ## 我先按一下 Tab 键,没有响应,然后我在按一下 Tab键
  6. pwck pwd pwhistory_helper pwscore
  7. pwconv pwdx pwmake pwunconv

路径补全( Tab 键 )

把用户给出的字符串当做路径开头,并在其指定上级目录下搜索以指定的字符串开头的文件

如果唯一, 直接补全。否则再次 Tab 将给出列表

命令行扩展

~ : 展开为用户的主目录 ~USERNAME : 展开为指定用户的家目录 {} : 可承载一个以逗号分割的列表,并将其展开为多个路径 /temp/{a,b} = / temp/a /temp/b echo {1..10} = 输出 1-10 echo {a..z} = 输出 a-z echo {00..20..2} = 输出 00 02 04 06 08 10 12 14 16 18 20 $() 或 ` : 把命令的输出打印给另一个命令的参数 echo "i amwhoami`” = i am root echo “i am $(whoami)” = i am root

  1. [root@localhost ~]# mkdir -p test/{a,b}/{x1,x2}
  2. [root@localhost ~]# tree test
  3. test
  4. ├── a
  5. ├── x1
  6. └── x2
  7. └── b
  8. ├── x1
  9. └── x2

命令的执行结果状态

bash 使用特殊变量 $? 保存最近一条命令的执行状态结果

0 : 成功 1-255 :失败

  1. [root@localhost ~]# ls
  2. [root@localhost ~]# echo $?
  3. 0
  4. [root@localhost ~]# mkdir test
  5. [root@localhost ~]# echo $?
  6. 0
  7. [root@localhost ~]# mkdir test
  8. mkdir: cannot create directory test’: File exists
  9. [root@localhost ~]# echo $?
  10. 1

命令别名(alias)

通过 alias 命令实现,在命令行中定义的别名,仅针对当前 shell 进程有效,如果想要永久有效,需要定义在配置文件。

当前用户 :~/.bashrc 所有用户 : /etc/bashrc

编辑配置文件中新配置不会立即生效,可以通过 source Config_File 来立即生效。

文件通配符(globbing)

bash 中用于实现文件名的通配功能, 主要有以下几种:

* 任意长度的任意字符
? 任意单个字符
[] 匹配指定范围内的任意单个字符
[0-9] 0-9 之间的数字
[a-z] 不区分字符大小写
[A-Z] 大写字母
[gkdaxue] 匹配列表中的任意一个字符
[^] 匹配指定范围外的任意单个字符
[^gkdaxue] 匹配列表中的所有字符以外的字符
~ 当前用户家目录
~gkdaxue 用户 gkdaxue 家目录

专用字符集合

[:digit:] 任意数字,相当于 0-9
[:lower:] 任意小写字母
[:upper:] 任意大写字母
[:alpha:] 任意大小写字母
[:alnum:] 任意数字和字母
[:space:] 空格
[:punct:] 标点符号

bash的快捷键

Ctrl + l 清屏,相当于 clear 命令
Ctrl + a 跳转到命令开始处
Ctrl + e 跳转到命令结尾处
Ctrl + c 取消命令的执行
Ctrl + u 删除行首到光标所在处的所有内容
Ctrl + k 删除光标所在处到行尾的所有内容
Ctrl + s 阻止屏幕输出,锁定
Ctrl + q 允许屏幕输出
Ctrl + o 执行当前命令,并重新显示本命令
Ctrl + f 光标向右移动一个字符
Ctrl + b 光标向左移动一个字符
Ctrl + xx 光标在命令行首和光标之间移动
Ctrl + w 从光标处向左删除至单词首
Ctrl + d 删除光标处的一个字符
Ctrl + h 删除光标钱的一个字符

I/0 重定向及管道

简而言之,输入重定向是指把文件导入到命令中,而输出重定向则是指把原本要输出到屏幕的数据信息写入到指定文件中。在日常的学习和工作中,相较于输入重定向,我们使用输出重定向的频率更高,所以又将输出重定向分为了标准输出重定向和错误输出重定向两种不同的技术,以及清空写入与追加写入两种模式。
打开的文件都有一个 fd :file descriptor(文件描述符)

标准输入重定向(STDIN,文件描述符为0):默认从键盘输入,也可从其他文件或命令中输入。 标准输出重定向(STDOUT,文件描述符为1):默认输出到屏幕。文件描述符可以省略不写 错误输出重定向(STDERR,文件描述符为2):默认输出到屏幕。文件描述符不可以省略

[root@localhost ~]# touch gkdaxue[root@localhost ~]# ll gkdaxue -rw-r—r—. 1 root root 0 May 9 09:49 gkdaxue [root@localhost ~]# ll gkdaxue2 ls: cannot access gkdaxue2: No such file or directory

在上述命令中,名为 gkdaxue 的文件是真实存在的,输出信息是该文件的一些相关权限、所有者、所属组、文件大小及修改时间等信息,这也是该命令的标准输出信息。而名为 gkdaxue2 的第二个文件是不存在的,因此在执行完ls命令之后显示的报错提示信息也是该命令的错误输出信息。那么,要想把原本输出到屏幕上的数据转而写入到文件当中,就要区别对待这两种输出信息。

标准输入重定向

符号 作用
命令 < 文件 将文件作为命令的标准输入
命令 << 分界符 从标准输入中读入,直到遇见分界符才停止
命令 < 文件1 > 文件2 将文件1作为命令的标准输入并将标准输出到文件2

标准输出重定向/错误输出重定向

符号 作用
命令 > 文件 将标准输出重定向到一个文件中(清空原有文件的数据)
命令 2> 文件 将错误输出重定向到一个文件中(清空原有文件的数据)
命令 >> 文件 将标准输出重定向到一个文件中(追加到原有内容的后面)
命令 2>> 文件 将错误输出重定向到一个文件中(追加到原有内容的后面)
命令 >> 文件 2>&1

命令 &>> 文件
将标准输出与错误输出共同写入到文件中(追加到原有内容的后面)

I/O重定向示例

使用标准输出即可将原本要输出到屏幕的信息写入到文件中,而错误的输出重定向则依然把信息输出到了屏幕上。

标准输出重定向

  1. [root@localhost ~]# echo 111 222
  2. 111 222
  3. [root@localhost ~]# echo 111 222 > input.txt ## 使用的是覆盖模式,所以只有当前的结果
  4. [root@localhost ~]# cat input.txt
  5. 111 222
  6. [root@localhost ~]# echo 111 222 > input.txt ## 使用的是覆盖模式,所以只有当前的结果
  7. [root@localhost ~]# cat input.txt
  8. 111 222
  9. [root@localhost ~]# echo 111 222 >> input.txt ## 使用的是追加模式,所以是之前的内容 + 现在的内容
  10. [root@localhost ~]# cat input.txt
  11. 111 222
  12. 111 222

错误输出重定向

  1. [root@localhost ~]# ll input.txt
  2. -rw-r--r--. 1 root root 16 May 9 11:40 input.txt
  3. [root@localhost ~]# ll input.txt 2> error.input ## 使用了 2>, 发现没有什么效果,继续输出了
  4. -rw-r--r--. 1 root root 16 May 9 11:40 input.txt
  5. [root@localhost ~]# cat error.input ## 查看文件内容也是空的
  6. # 使用标准输出即可将原本要输出到屏幕的信息写入到文件中,而错误的输出重定向则依然把信息输出到了屏幕上。
  7. [root@localhost ~]# ll test.txt ## 查看一个并不存在的文件,报出了一个错误
  8. ls: cannot access test.txt: No such file or directory
  9. [root@localhost ~]# ll test.txt 2> error.input ## 然后把错误重定向覆盖到一个文件中
  10. [root@localhost ~]# cat error.input ## 查看文件内容
  11. ls: cannot access test.txt: No such file or directory
  12. [root@localhost ~]# ll test.txt 2>> error.input ## 然后把错误重定向追加到一个文件中
  13. [root@localhost ~]# cat error.input
  14. ls: cannot access test.txt: No such file or directory
  15. ls: cannot access test.txt: No such file or directory
  16. ## 我们不区分标准还是错误信息,只要命令有输出信息则全部追加写入到文件中
  17. ## 这种就要使用到 &>> 操作符了,全部写入到文件中
  18. [root@localhost ~]# ll input.txt &>> all.input
  19. [root@localhost ~]# ll xxxxx.txt &>> all.input
  20. [root@localhost ~]# cat all.input
  21. -rw-r--r--. 1 root root 16 May 9 11:40 input.txt
  22. ls: cannot access xxxxx.txt: No such file or directory

输入重定向

  1. ## 输入重定向的作用是把文件直接导入到命令中
  2. [root@localhost ~]# wc -l input.txt
  3. 2 input.txt
  4. [root@localhost ~]# wc -l < input.txt ## 为啥输出的没有文件名称呢?
  5. 2

这是因为此前使用“wc -l input.txt”是一种非常标准的“命令+参数+对象”的执行格式,而这次的“wc -l < input.txt”则是将 input.txt 文件内的内容通过操作符导入到的命令中,没有被当作命令对象进行执行的过程,因此wc命令只能读到信息流的数据,没有文件名称的信息。

set -C : 禁止将内容覆盖输出已有文件中

set +C : 解除禁止覆盖已有文件中

  1. [root@localhost ~]# ll input.txt
  2. ls: cannot access input.txt: No such file or directory
  3. [root@localhost ~]# echo aaa bbb > input.txt ## 新建的一个文件
  4. [root@localhost ~]# cat input.txt
  5. aaa bbb
  6. ## 设置不允许覆盖已有文件内容
  7. [root@localhost ~]# set -C
  8. [root@localhost ~]# echo aaa bbb > input.txt
  9. -bash: input.txt: cannot overwrite existing file
  10. [root@localhost ~]# cat input.txt
  11. aaa bbb
  12. ## 不允许覆盖,但是可以正常追加
  13. [root@localhost ~]# echo aaa bbb >> input.txt
  14. [root@localhost ~]# cat input.txt
  15. aaa bbb
  16. aaa bbb
  17. ## 设置的不允许覆盖,但是我们想要强制覆盖
  18. [root@localhost ~]# echo aaa bbb >| input.txt
  19. [root@localhost ~]# cat input.txt
  20. aaa bbb
  21. ## 解除不允许覆盖
  22. [root@localhost ~]# set +C
  23. [root@localhost ~]# echo 111 222 > input.txt
  24. [root@localhost ~]# cat input.txt
  25. 111 222

管道命令符 |

管道命令符的作用也可以用一句话来概括“把前一个命令原本要输出到屏幕的信息当作是后一个命令的标准输入”。最后一个命令会在当前 shell 进程的子 shell 进程中执行。管道命令仅能处理 standard output, 对于 standard error output 会予以忽略。命令格式如下:

Command1 | Command2 | Command3 | …

  1. [root@localhost ~]# cat /etc/passwd | wc -l
  2. 21
  3. [root@localhost ~]# cut -d ":" -f 1 /etc/passwd | head -n 2
  4. root
  5. bin
  6. [root@localhost ~]# cut -d ":" -f 1 /etc/passwd | head -n 2 | tr [a-z] [A-Z]
  7. ROOT
  8. BIN