命令历史
命令行历史
!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 | 从历史搜索中退出 |
## !NUM 调用历史命令中的第 NUM 条命令
[root@gkdaxue ~]# history 2
123 pwd
124 history 2
[root@gkdaxue ~]# !123
pwd
/root
## !STRING : 调用历史命令中最近一条以 STRING 开头的命令
[root@gkdaxue ~]# history 2
127 pwd
128 history 2
[root@gkdaxue ~]# !pw
pwd
/root
## !! :执行上一条命令
[root@gkdaxue ~]# pwd
/root
[root@gkdaxue ~]# !!
pwd
/root
## !$:p 打印输出 !$ (上一条命令的最后一个参数)的内容
[root@localhost ~]# cat /etc/sysconfig/network-scripts/ifcfg-eno16777736
[root@localhost ~]# !$:p
/etc/sysconfig/network-scripts/ifcfg-eno16777736
## !*:p
[root@localhost ~]# echo 111 222
111 222
[root@localhost ~]# !*:p
111 222
## ^string 删除上一条命令的第一个 string
[root@localhost ~]# echo 111 111 222
111 111 222
[root@localhost ~]# ^111
echo 111 222
111 222
## ^string1^string2 : 将上一条命令中的第一个 string1 替换成 string2
[root@localhost ~]# echo 111 111 222
111 111 222
[root@localhost ~]# ^111^222
echo 222 111 222
222 111 222
## !:gs/string1/string2 :将上一条命令中的所有 string1 替换为 string2
[root@localhost ~]# echo 111 111 111
111 111 111
[root@localhost ~]# !:gs/111/222
echo 222 222 222
222 222 222
## !$ : 调用前一个命令中的最后一个参数
[root@localhost ~]# echo 111 222 333
111 222 333
[root@localhost ~]# echo !$
echo 333
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 条命令的所有参数 |
[root@localhost ~]# echo aaa bbb ccc ddd
aaa bbb ccc ddd
[root@localhost ~]# echo !^
echo aaa
aaa
[root@localhost ~]# echo aaa bbb ccc ddd
aaa bbb ccc ddd
[root@localhost ~]# echo !$
echo ddd
ddd
[root@localhost ~]# echo aaa bbb ccc ddd
aaa bbb ccc ddd
[root@localhost ~]# echo !*
echo aaa bbb ccc ddd
aaa bbb ccc ddd
[root@localhost ~]# echo aaa bbb ccc ddd
aaa bbb ccc ddd
[root@localhost ~]# echo !:3
echo ccc
ccc
[root@localhost ~]# history
...
575 echo aaa bbb ccc ddd
[root@localhost ~]# echo !575:^
echo aaa
aaa
[root@localhost ~]# echo !575:$
echo ddd
ddd
[root@localhost ~]# echo !575:3
echo ccc
ccc
[root@localhost ~]# echo !575:*
echo aaa bbb ccc ddd
aaa bbb ccc ddd
命令补全( Tab 键 )
直接补全 : 用户给定的字符串只有一条唯一对应的命令 给出列表 : 以用户给定的字符串为开头对应的命令不唯一,再次按 Tab 键则会给出列表
## 比如我想输入 echo 命令
[root@localhost ~]# ech ## 然后直接按 Tab 键, 自动变为如下
[root@localhost ~]# echo
## 给出列表
[root@localhost ~]# pw ## 我先按一下 Tab 键,没有响应,然后我在按一下 Tab键
pwck pwd pwhistory_helper pwscore
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 am
whoami`” = i am root echo “i am $(whoami)” = i am root
[root@localhost ~]# mkdir -p test/{a,b}/{x1,x2}
[root@localhost ~]# tree test
test
├── a
│ ├── x1
│ └── x2
└── b
├── x1
└── x2
命令的执行结果状态
bash 使用特殊变量 $? 保存最近一条命令的执行状态结果
0 : 成功 1-255 :失败
[root@localhost ~]# ls
[root@localhost ~]# echo $?
0
[root@localhost ~]# mkdir test
[root@localhost ~]# echo $?
0
[root@localhost ~]# mkdir test
mkdir: cannot create directory ‘test’: File exists
[root@localhost ~]# echo $?
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重定向示例
使用标准输出即可将原本要输出到屏幕的信息写入到文件中,而错误的输出重定向则依然把信息输出到了屏幕上。
标准输出重定向
[root@localhost ~]# echo 111 222
111 222
[root@localhost ~]# echo 111 222 > input.txt ## 使用的是覆盖模式,所以只有当前的结果
[root@localhost ~]# cat input.txt
111 222
[root@localhost ~]# echo 111 222 > input.txt ## 使用的是覆盖模式,所以只有当前的结果
[root@localhost ~]# cat input.txt
111 222
[root@localhost ~]# echo 111 222 >> input.txt ## 使用的是追加模式,所以是之前的内容 + 现在的内容
[root@localhost ~]# cat input.txt
111 222
111 222
错误输出重定向
[root@localhost ~]# ll input.txt
-rw-r--r--. 1 root root 16 May 9 11:40 input.txt
[root@localhost ~]# ll input.txt 2> error.input ## 使用了 2>, 发现没有什么效果,继续输出了
-rw-r--r--. 1 root root 16 May 9 11:40 input.txt
[root@localhost ~]# cat error.input ## 查看文件内容也是空的
# 使用标准输出即可将原本要输出到屏幕的信息写入到文件中,而错误的输出重定向则依然把信息输出到了屏幕上。
[root@localhost ~]# ll test.txt ## 查看一个并不存在的文件,报出了一个错误
ls: cannot access test.txt: No such file or directory
[root@localhost ~]# ll test.txt 2> error.input ## 然后把错误重定向覆盖到一个文件中
[root@localhost ~]# cat error.input ## 查看文件内容
ls: cannot access test.txt: No such file or directory
[root@localhost ~]# ll test.txt 2>> error.input ## 然后把错误重定向追加到一个文件中
[root@localhost ~]# cat error.input
ls: cannot access test.txt: No such file or directory
ls: cannot access test.txt: No such file or directory
## 我们不区分标准还是错误信息,只要命令有输出信息则全部追加写入到文件中
## 这种就要使用到 &>> 操作符了,全部写入到文件中
[root@localhost ~]# ll input.txt &>> all.input
[root@localhost ~]# ll xxxxx.txt &>> all.input
[root@localhost ~]# cat all.input
-rw-r--r--. 1 root root 16 May 9 11:40 input.txt
ls: cannot access xxxxx.txt: No such file or directory
输入重定向
## 输入重定向的作用是把文件直接导入到命令中
[root@localhost ~]# wc -l input.txt
2 input.txt
[root@localhost ~]# wc -l < input.txt ## 为啥输出的没有文件名称呢?
2
这是因为此前使用“wc -l input.txt”是一种非常标准的“命令+参数+对象”的执行格式,而这次的“wc -l < input.txt”则是将 input.txt 文件内的内容通过操作符导入到的命令中,没有被当作命令对象进行执行的过程,因此wc命令只能读到信息流的数据,没有文件名称的信息。
set -C : 禁止将内容覆盖输出已有文件中
set +C : 解除禁止覆盖已有文件中
[root@localhost ~]# ll input.txt
ls: cannot access input.txt: No such file or directory
[root@localhost ~]# echo aaa bbb > input.txt ## 新建的一个文件
[root@localhost ~]# cat input.txt
aaa bbb
## 设置不允许覆盖已有文件内容
[root@localhost ~]# set -C
[root@localhost ~]# echo aaa bbb > input.txt
-bash: input.txt: cannot overwrite existing file
[root@localhost ~]# cat input.txt
aaa bbb
## 不允许覆盖,但是可以正常追加
[root@localhost ~]# echo aaa bbb >> input.txt
[root@localhost ~]# cat input.txt
aaa bbb
aaa bbb
## 设置的不允许覆盖,但是我们想要强制覆盖
[root@localhost ~]# echo aaa bbb >| input.txt
[root@localhost ~]# cat input.txt
aaa bbb
## 解除不允许覆盖
[root@localhost ~]# set +C
[root@localhost ~]# echo 111 222 > input.txt
[root@localhost ~]# cat input.txt
111 222
管道命令符 |
管道命令符的作用也可以用一句话来概括“把前一个命令原本要输出到屏幕的信息当作是后一个命令的标准输入”。最后一个命令会在当前 shell 进程的子 shell 进程中执行。管道命令仅能处理 standard output, 对于 standard error output 会予以忽略。命令格式如下:
Command1 | Command2 | Command3 | …
[root@localhost ~]# cat /etc/passwd | wc -l
21
[root@localhost ~]# cut -d ":" -f 1 /etc/passwd | head -n 2
root
bin
[root@localhost ~]# cut -d ":" -f 1 /etc/passwd | head -n 2 | tr [a-z] [A-Z]
ROOT
BIN