shell
确认当前终端tty
使用的Shell
类型:
Shell(Unix Shell)
是一种命令行解释器,是Unix
操作系统下最传统的人机接口。 Shell
脚本是解释执行的,不需要编译,和大部分的编程语言很相似,也有基本的变量和流程控制语句。我们平时使用Shell
有两种方式:
-
输入命令,执行,这种方式称为交互式(
Interactive
); -
批处理(
Batch
)方式,用户事先写好Shell
脚本文件,然后顺序执行脚本中的命令。
第一个Shell
环境是Thompson Shell
,在贝尔实验室开发并于1971年发布。
现代Shell
最突出的祖先是被称为sh
的BourneShell
,这是以在AT&T
工作的创始人Stephen Bourne
命名的。
Shell
一直在基于这个概念,不断添加各种新功能,演变出很多种的Shell
。
例如,很早版本的OS X
中使用的是:
-
tcsh
作为默认的Shell
。这是由csh(C shell)
,一种类似C
语言的Shell
演变而来。
在OS X 10.3
版与10.4
版之后,默认的Shell
是:
-
bash
,由GNU
开发。
除了默认的bash
,现在macOS
中,默认的Shell
变成了zsh
。这是一种由Paul Falstad
于1990年开发的。它是一个Bourne
式Shell
,它使用bash
和previous shell
的特性,并添加了更多的特性:
-
拼写检查功能
-
内置的编程特性
-
友好的交互
与此同时,macOS
还提供了很多其他种类的Shell
:
.bashrc
、.bash_profile
和.zshrc
作用与区别
在使用命令行工具时,我们可能会遇到一些教程,可能需要你把一些配置写入到.bashrc
、.bash_profile
或者.zshrc
等。那么这几个文件到底有什么作用和区别?
首先,从文件名称判断.bashrc
、.bash_profile
是给Bash
来使用的。而.zshrc
是给zsh
来使用的。
交互式登录和非登录Shell
当调用Shell
时,Shell
从一组启动文件中读取信息并执行命令。读取什么文件就取决于Shell
是作为交互式登录还是非登录调用。
换言之,Shell
分为交互式的或非交互式的:
-
交互式
Shell
是读取和写入到用户终端的Shell
程序,用户在终端上输入命令,并在回车后立即执行。 -
非交互式
Shell
是与终端不相关的Shell
程序,例如执行脚本时。
交互式Shell
可以是登录Shell
,也可以是非登录Shell
。
当用户通过ssh
或本地远程登录到终端时,或者使用--login
选项启动时,将调用登录shell
。
当作为交互式登录Shell
调用时,Bash
会先查找/etc/profile
文件,如果该文件存在,它将运行文件中列出的命令。然后,搜索
~/.bash_profile
,~/.bash_login
以及~/.profile
文件,顺序读取。
当Bash
作为交互式非登录shell
调用时,会读取~/.bashrc
。
所以说,.bashrc
和.bash_profile
之间的区别是,.bash_profile
当Bash
作为交互式登录shell
调用时被读取并执行,而.bashrc
对于交互式非登录shell
被执行。
大多数Linux/Unix
发行版都使用~/.profile
代替~/.bash_profile
。~/.profile
所有shell
都读取该文件,而~/.bash_profile
只有Bash
才会读取该文件。
~/.zshrc
是zsh
的交互式shell
的用户配置。
对于Bash
,它们的工作方式如下:
- 读取适当的内容,执行
A
,然后执行B
,然后执行C
,依此类推。B1
,B2
,B3
表示仅执行找到的那些文件中的第一个。
+----------------+-----------+-----------+------+
| |Interactive|Interactive|Script|
| |login |non-login | |
+----------------+-----------+-----------+------+
|/etc/profile | A | | |
+----------------+-----------+-----------+------+
|/etc/bash.bashrc| | A | |
+----------------+-----------+-----------+------+
|~/.bashrc | | B | |
+----------------+-----------+-----------+------+
|~/.bash_profile | B1 | | |
+----------------+-----------+-----------+------+
|~/.bash_login | B2 | | |
+----------------+-----------+-----------+------+
|~/.profile | B3 | | |
+----------------+-----------+-----------+------+
|BASH_ENV | | | A |
+----------------+-----------+-----------+------+
| | | | |
+----------------+-----------+-----------+------+
| | | | |
+----------------+-----------+-----------+------+
|~/.bash_logout | C | | |
+----------------+-----------+-----------+------+
对于zsh
,它们的工作方式如下:
- 读取适当的内容,执行
A
,然后执行B
,然后执行C
,依此类推。
+----------------+-----------+-----------+------+
| |Interactive|Interactive|Script|
| |login |non-login | |
+----------------+-----------+-----------+------+
|/etc/zshenv | A | A | A |
+----------------+-----------+-----------+------+
|~/.zshenv | B | B | B |
+----------------+-----------+-----------+------+
|/etc/zprofile | C | | |
+----------------+-----------+-----------+------+
|~/.zprofile | D | | |
+----------------+-----------+-----------+------+
|/etc/zshrc | E | C | |
+----------------+-----------+-----------+------+
|~/.zshrc | F | D | |
+----------------+-----------+-----------+------+
|/etc/zlogin | G | | |
+----------------+-----------+-----------+------+
|~/.zlogin | H | | |
+----------------+-----------+-----------+------+
| | | | |
+----------------+-----------+-----------+------+
| | | | |
+----------------+-----------+-----------+------+
|~/.zlogout | I | | |
+----------------+-----------+-----------+------+
|/etc/zlogout | J | | |
+----------------+-----------+-----------+------+
确认当前是登录还是非登录shell
在tty
中执行echo $0
,输出的Shell
如果前面带-
,说明是登录Shell
。
配置建议
-
bash
:
- 将配置选项放到
~/.bashrc
中,然后在~/.bash_profile
中通过source
调用。
- zsh`:
- 建议仍然将配置选项放到
~/.bashrc
,~/.bash_profile
中通过source
调用,最后在~/.zshrc
中source
调用~/.bash_profile
。
常用命令参考
ag
命令
ag
超快的文件搜索工具,与grep
相比,搜索速度更快。
c++filt
命令
c++filt
命令可用于解析C++
和Java
中被修饰的符号,比如变量与函数名称。
tree
命令
tree
命令以树状图列出目录的内容。
cp
命令
cp
是copy
的缩写,cp
命令用于复制文件/文件夹。
参数:
-a, --archive 等于-dR --preserve=all--backup[=CONTROL 为每个已存在的目标文件创建备份
-b 类似--backup 但不接受参数--copy-contents 在递归处理是复制特殊文件内容
-d 等于--no-dereference --preserve=links
-f, --force 如果目标文件无法打开则将其移除并重试(当 -n 选项存在时则不需再选此项)
-i, --interactive 覆盖前询问(使前面的 -n 选项失效)
-H 跟随源文件中的命令行符号链接
-l, --link 链接文件而不复制
-L, --dereference 总是跟随符号链接
-n, --no-clobber 不要覆盖已存在的文件(使前面的 -i 选项失效)
-P, --no-dereference 不跟随源文件中的符号链接
-p 等于--preserve=模式,所有权,时间戳--preserve[=属性列表 保持指定的属性
(默认:模式,所有权,时间戳),如果可能保持附加属性:环境、链接、xattr 等
-R, -r, --recursive 复制目录及目录内的所有项目
-t --target-directory=DIRECTORY 将所有源文件拷贝到目标目录
-T, --no-target-directory 目标为文件而不是文件夹
ln
命令
所谓的链接(link
),我们可以将其视为档案的别名,而链接又可分为两种:
- 硬链接(
hard link
),意思是一个档案可以有多个名称;
-
硬链接,以文件副本的形式存在。但不占用实际空间;
-
不允许给目录创建硬链接;
-
硬链接只有在同一个文件系统中才能创建;
- 软链接(
symbolic link
),意思是产生一个特殊的档案,该档案的内容是指向另一个档案的位置。
-
软链接,以路径的形式存在。类似于快捷方式;
-
软链接可以跨文件系统,硬链接不可以;
-
软链接可以对一个不存在的文件名进行链接;
-
软链接可以对目录进行链接。
sed
命令
通常要进行文本处理,sed
是一个非常强大的文本处理命令工具。 配合正则表达式可以进行文本搜索、替换、插入、删除等操作。处理时,把当前处理的行存储在临时缓冲区中,称为模式空间(pattern space
),接着用sed
命令处理缓冲区中的内容,处理完成后,把缓冲区的内容送往屏幕。接着处理下一行,这样不断重复,直到文件末尾。文件内容并没有改变。
grep
命令
grep
命令全称是Global Regular Expression Print
,是一种强大的文本搜索工具,它能使用正则表达式搜索文本,并把匹配的行打印出来。
主要参数:
ls
命令
ls
命令用来显示目标列表。
drwxr-xr-x 2 root root 48 2020-11-27 13:34 test/
第一个栏位,表示文件的属性。件基本上分为三个属性:可读(r
),可写(w
),可执行(x
)。数字表示:1表示可执行权限,2表示可写权限,4表示可读权限。
第一个字母表示文件类型:
-
-
,普通文件。 -
d
,目录,是dirtectory
的缩写。 -
l
,符号链接。 -
b
,块设备文件。 -
c
,字符设备文件。
紧接着的3*3
个字符分3
组,各指示此文件的读、写、执行权限,对于owner
、group
、others
而言。
因为Linux/Unix
是多用户多任务系统,所以一个文件可能同时被许多人使用,所以我们一定要设好每个文件的权限,其文件的权限位置排列顺序是(以-rwxr-xr-x
为例):
rwx(Owner)r-x(Group)r-x(Other)
```
第二个栏位,表示文件个数。如果是文件的话,那这个数目自然是1了,如果是目录的话,那它的数目就是该目录中的文件个数了。
第三个栏位,表示该文件或目录的拥有者。若使用者目前处于自己的`Home`,那这一栏大概都是它的账号名称。
第四个栏位,表示所属的组(`group`)。每一个使用者都可以拥有一个以上的组,不过大部分的使用者应该都只属于一个组,只有当[系统管理员]希望给予某使用者特殊权限时,才可能会给他另一个组。
第五栏位,表示文件大小。文件大小用`byte`来表示,而空目录一般都是`1024byte`,当然可以用其它参数使文件显示的单位不同,如使用`ls –k`就是用`kb`显示一个文件的大小单位,不过一般我们还是以`byte`为主。
第六个栏位,表示最后一次修改时间。以“月,日,时间”的格式表示,如`Aug 15 5:46`表示`8月15日早上5:46分`。
第七个栏位,表示文件名。我们可以用`ls –a`显示隐藏的文件名。
`–rwxr-xr-x`转换成权限数字为755。即:
1. `rwx`即4+2+1=7;
2. `r-x`即4+1=5;
3. `r-x`即4+1=5。
## `stat`命令
`stat`命令用于显示文件或文件系统的详细信息。在显示文件信息时,比`ls`命令更加详细。
参数:
-L, --dereference: 跟随符号链接解析原文件而非符号链接;
-f, --file-system: 显示文件所在文件系统信息而非文件信息;
-c,--format=FORMAT: 以指定格式输出,而非默认格式;
--printf=FORMAT: 以指定格式输出,而非默认格式。与--format作用类似,但可以解释反斜杠转义字符,比如换行符\n;
-t, --terse: 简洁模式输出,只显示摘要信息;
--help: 显示帮助信息;
--version: 显示版本信息。
显示文件信息可用格式控制符如下:
%a:以八进制显示访问权限
%A:以可读形式显示访问权限
%b:显示占有块数
%B:显示每一块占有的字节数
%C:SELinux security context string
%d:十进制显示文件所在设备号
%D:十六进制显示文件所在设备号
%f:十六进制显示文件类型
%F:文件类型。Linux下文件类型主要分为普通文件、目录、字符设备文件、块设备文件、符号链接文件、套接字等
%g:文件所有者组ID
%G:文件所有者组名称
%h:文件硬链接数
%i:inode号
%m:文件所在磁盘分区挂载点,比如/data
%n:文件名称
%N:单引号括起来的文件名称,如果是软链接,则同时显示指向的文件名称
%o:optimal I/O transfer size hint
%s:实际文件大小,单位字节
%t:major device type in hex, for character/block device special files
%T:minor device type in hex, for character/block device special files
%u:所有者用户ID
%U:所有者用户名称
%w:文件创建时间,输出-表示无法得知
%W:文件创建时间,输出Unix时间戳,0表示无法得知
%x:可读形式输出最后访问时间atime
%X:Unix时间戳输出最后访问时间atime
%y:可读形式输出最后修改时间mtime
%Y:Unix时间戳输出后修改时间mtime
%z:可读形式输出最后状态改变时间ctime
%Z:Unix时间戳输出最后状态改变时间ctime
显示文件系统信息可用格式控制符有:
%a:非超级用户可使用的自由block数
%b:文件系统总block数
%c:文件系统总文件节点数
%d:可用文件节点数
%f:可用文件block数
%i:十六进制文件系统ID
%l:最大文件名称长度
%n:文件名称
%s:一个块的大小,单位字节(for faster transfers)
%S:一个块的基本大小,单位字节(用于统计block的数量)
%t:十六进制输出文件系统类型
%T:可读形式输出文件系统类型
Shell
里面的括号
-
${a}
:变量a
的值, 在不引起歧义的情况下可以省略大括号。 -
$(cmd)
:命令替换, 和cmd
效果相同。 -
$((exp))
:增强括号的用法和expr exp
效果相同, 计算数学表达式exp
的数值,,其中exp
只要符合C
语言的运算规则即可,甚至三目运算符和逻辑表达式都可以计算。可以省略$
。比如:
for((i=0;i<5;i++))
# 如果不使用双括号
for i in seq 0 4
for i in {0..4}
if (($i<5))
# 如果不使用双括号
if [ $i -lt 5 ]
-
(cmd1;cmd2;cmd3)
新开一个子shell
顺序执行命令cmd1
、cmd2
,cmd3
, 各命令之间用分号隔开,最后一个命令后可以没有分号. -
{ cmd1;cmd2;cmd3;}
: 在当前shell
顺序执行命令cmd1
、cmd2
和cmd3
。 各命令之间用分号隔开,最后一个命令后必须有分号,第一条命令和左括号之间必须用空格隔开。
Shell
里面的中括号(包括[]
与[[]]
)可用于一些条件的测试:
-
算术比较,比如一个变量是否为0:
[ $var -eq 0 ]
。 -
文件属性测试,比如一个文件是否存在:
[ -e $var ]
。 是否是目录:[ -d $var ]
。 -
[[]]
:字符串比较,增强方括号用法,双括号中的表达式可以使用&&
、||
、<
、>
等语法。比如:
# 比较两个字符串是否相同
[[ $var1 = $var2 ]]
if [[ $a != 1 && $a != 2 ]]
# 如果不使用[[]]
if [ $a -ne 1] && [ $a != 2 ]
if [ $a -ne 1 -a $a != 2 ]
对{}
和()
而言,括号中的重定向符只影响该条命令, 而括号外的重定向符影响到括号中的所有命令.
Shell
里面的单引号和双引号
首先,单引号和双引号,都是为了解决中间有空格的问题。
因为空格在shell
中作为一个很典型的分隔符,比如string1=this is astring
,这样执行就会报错。为了避免这个问题,因此就产生了单引号和双引号。他们的区别在于,单引号将剥夺其中的所有字符的特殊含义,而双引号中的 $
(参数替换)和反引号(命令替换与$()
作用一样)是例外。所以,两者基本上没有什么区别,除非在内容中遇到了参数替换符$和命令替换符反引号。
Shell
标准输出、标准输入和标准错误输出
标准输出和标准错误输出可以将内容重定向输出到指定的设备(如打印机)或文件中,
标准输入可以使用文件或其他输入替换手动输入。
-
标准输入(
stdin
):代码为0,符号:< 或者<<
; -
标准输出(
stdout
):代码为1,符号:>或者>>
; -
标准错误输出(stderr):代码为2,符号:
2>或者2>>
。
单箭头和双箭头的区别:
- 对于输出:
-
单箭头:当指定的文件不存在时,创建新文件写入数据;当文件存在时,清空原文件的内容写入数据。
-
双箭头:当指定的文件不存在时,创建新文件写入数据;当文件存在时,在原件内容的最后追加写入数据。
- 对于输入:
-
单箭头:将文件或其他输入作为标准输入。(
<
的左边必须是命令,<
右边的输入内容作为命令的输入)。 -
双箭头:结束输入。
将标准输出和错误输出重定向到一个文件上:
- 将
stdin
和stderr
无序输出到one.log
:
grep "Cat" file.log > one.log 2>one.log
- 将
stdin
和stderr
序有输出到one.log
:
#首先stdin重定向到one.log,然后使用2>&1表示stderr重定向至stdin,stderr在stdin之后输入到one.log中
grep "Cat" file.log > one.log 2>&1
# 简写
grep "Cat" file.log &> one.log
网友评论