Shell

TIP

最后更新时间:2019年8月24日

字数:17161

参考资料

Shell

什么是Shell

  • 工作在Linux内核与用户之间的解释程序

    • 相当于操作系统的外壳
    • 向Linux内核传达用户指令的“解释官”
    • 通常是指BASH(/bin/bash)
  • 确切地说,Shell 是一个命令行解释器,它为用户提供了一个向 Linux 内核发送请求以便运行程序的界面系统级程序,用户可以用 Shell 来启动、挂起、停止甚至编写一些程序。

  • Windows下的Shell解释器

    • C:/Windows/Syetem32/cmd.exe

TIP

  • 我们平时所说的 Shell 可以理解为 Linux 系统提供给用户的使用界面。
  • Shell 为用户提供了输入命令和参数并可得到命令执行结果的环境。
  • 当一个用户登录 Linux 之后,系统初始化程序 init 就根据 /etc/passwd 文件中的设定,为每个用户运行一个被称为 Shell(外壳)的程序

Shell作用

  • Shell 处在内核与外层应用程序之间,起着协调用户与系统的一致性、在用户与系统之间进行交互的作用
  • Shell 接收用户输入的命令,并把用户的命令从类似 abed 的 ASCII 码解释为类似 0101 的机器语言,然后把命令提交到系统内核处理
  • 当内核处理完毕之后,把处理结果再通过 Shell 返回给用户

Shell与一般命令对比

  • Shell 与其他 Linux 命令一样,都是实用程序,但它们之间还是有区别的:
    • 一旦用户注册到系统后,Shell 就被系统装入内存并一直运行到用户退出系统为止;而一般命令仅当被调用时,才由系统装入内存执行

    • 与一般命令相比,Shell 除了是一个命令行解释器,同时还是一门功能强大的编程语言,易编写,易调试,灵活性较强

Shell编程

  • Shell作为一种命令级语言,Shell 是解释性的,组合功能很强,与操作系统有密切的关系,可以在 Shell 脚本中直接使用系统命令;大多数 Linux 系统的启动相关文件(一般在 /etc/rc.d 目录下)都是使用 Shell 脚本编写的
  • 同传统的编程语言一样,Shell 提供了很多特性,这些特性可以使 Shell 脚本编程更为有用,如数据变量、参数传递、判断、流程控制、数据输入和输出、子程序及中断处理等
  • 说了这么多,其实我们在 Linux 中操作的命令行界面就是 Linux 的 Shell,也就是 Bash,但是我们的图形界面是 Shell 吗?其实从广义讲,图形界面当然也是 Shell,因为它同样用来接收用户的操作,并传递到内核进行处理。不过,这里的 Shell 主要指的是 Bash

查看当前的Shell 环境

echo $SHELL
结果:/bin/bash
1
2

查看Mac OS系统已安装的Shell

  • /etc/shells文件中记录了当前系统已安装的Shell
cat /etc/shells
# List of acceptable shells for chpass(1).
# Ftpd will not allow users to connect who are not using
# one of these shells.

/bin/bash
/bin/csh
/bin/ksh
/bin/sh
/bin/tcsh
/bin/zsh
1
2
3
4
5
6
7
8
9
10
11

手动选择Shell环境

  • Mac OS 上chsh命令
  • 直接输入Shell名称
    • 相当于新建一个子环境(父 -> 子进程)

常见Shell 环境

  • bash
  • sh
  • ash
  • csh/tcsh
  • ksh
  • zch

bash

  • bash:Bourne Again Shell
  • 是自由软件基金会( GNU )开发的一个Shell
  • 是linux标准的默认shell

TIP

bash基于Bourne shell,吸收了C shell和Korn shell的一些特性

bash完全兼容sh,也就是说,用sh写的脚本可以不加修改的在bash中执行

sh

  • sh:Bourne Shell
  • 是由AT&T Bell实验室的 Steven Bourne为AT&T的Unix开发的
  • sh是Unix的默认Shell,也是其它Shell的开发基础
  • Bourne Shell在编程方面相当优秀,但在处理与用户的交互方面不如其它几种Shell

TIP

现代的大部分 Linux 上,sh 已经被 bash 代替,/bin/sh往往是指向/bin/bash的符号链接

ash

  • ash Shell是由Kenneth Almquist编写的
  • ash是Linux 中占用系统资源最少的一个小Shell
  • ash只包含24个内部命令,因而使用起来很不方便

csh(tcsh)

  • csh:CShell
  • csh是加州伯克利大学的Bill Joy为BSD Unix开发的,共有52个内部命令,与sh不同,它的语法与C语言很相似
  • csh提供了Bourne Shell所不能处理的用户交互特征,如命令补全、命令别名、历史命令替换等,但是,C Shell与BourneShell并不兼容
  • csh:其实是指向/bin/tcsh这样的一个Shell,也就是说,csh其实就是tcsh

ksh

  • ksh:Korn Shell
  • ksh是AT&T Bell实验室的David Korn开发的,它集合了C Shell和Bourne Shell的优点,并且与Bourne Shell向下完全兼容
  • Korn Shell的效率很高,其命令交互界面和编程交互界面都很好

zch

  • zch是Linux 最大的Shell之一,由Paul Falstad完成,共有84 个内部命令
  • 如果只是一般的用途,没有必要安装这样的Shell

交互方式

  • 交互式
  • 非交互式

交互式

  • 人工干预、智能化程度高
  • 逐条解释执行,效率低

非交互式

  • 需要提前设计、只能换难度大
  • 批量执行、效率高
  • 方便在后台静默执行

脚本

提前写好的可执行代码,用来完成特定任务的文件

  • 特点
    • 顺序、批处理
    • 解释型程序(需要解释器)
  • 常见的脚本语言
    • Bash Shell
    • JavaScript(前端)
    • Python、Ruby、PHP、Perl、JSP、ASP、CGI等

Shell脚本使用

声明Shell环境

#!/bin/bash
# 第一行是声明shell环境(Sha-Bang)
echo '你好'
1
2
3

添加注释

  • Shell脚本编写的时候,和我们写普通代码一样,也是需要注释的

  • Shell中添加注释是一个井号 #

运行Shell脚本

方法一:作为指定Shell解释程序的参数

  • sh + 代码文件路径
    • 等同于:bash + 代码文件路径
    • 因为sh是指向bash的快捷方式,大部分sh都被bash代替了,sh基本都是指向bash的快捷方式
  • 点(.)+ 代码文件路径
    • 等同于:source + 代码文件路径
    • 在Linux中点号和source是内建的两个命令

方法二:作为可独立运行的脚本程序

  • 为Shell代码文件添加x权限
  • 指定脚本路径即可
# +x 是给文件添加可执行权限
chmod +x ./demo1.sh

# 直接输入文件名,就可以执行具有可执行权限的文件
./demo1.sh
1
2
3
4
5

调试Shell脚本

方法一:直接观察执行过程

  • 执行中的目录输出和报错信息
  • 与用户的交互

方法二:开启调试模式

  • sh -X 脚本文件

alias

设置一个别名,即为一个长命令起一个新的名字

设置一个别名

alias   alias_name='origin_command'

# 示例(临时设置,关闭命令行就没了,长期设置看后面教程)
alias ll='ls -al'
1
2
3
4
  • alias是指定别名命令的关键字
  • alias_name 是用户指定的别名
  • origin_command 是以空格分割的字符串
  • 注意:等号两边不能有空格

TIP

注意:命令别名的优先级要高于命令本身。所以,除非你确定原命令是不需要的,否则别名不能和系统命令重名

命令执行时的顺序

  1. 第一顺位执行用绝对路径或相对路径执行的命令
  2. 第二顺位执行别名
  3. 第三顺位执行 Bash 的内部命令
  4. 第四顺位执行按照 $PATH 环境变量定义的目录査找的第一条命令

删除一个别名

unalias [-a][alias_name]

# 示例:删除刚才设置的ll命令
unalias ll
1
2
3
4
  • unalias -a 删除所有已设置的别名
  • unalias alias_name 仅删除alias_name的别名

设置永久别名

们使用命令定义别名,那么这个别名只是临时生效,一旦注销或重启系统,这个别名就马上消失了。为了让这个别名永久生效,可以把别名写入环境变量配置文件 ~/.bashrc 中

# 环境变量配置文件示例:
# vi /root/.bashrc
# .bashrc
# User specific aliases and functions
alias rm='rm -i'
alias cp='cp -i'
alias mv='mv -i'
alias vi='vim'

1
2
3
4
5
6
7
8
9

配置完,必须刷新文件才可以永久生效:source .bash_profile 或者 source .bashrc 或者 . .bashrc

TIP

alias命令写入~/.bash_profile或者~/.bashrc 其实都是可以的

注意:文件中添加后有时候,也是不管的,必须刷新环境变量文件才行

关于“.bash_profile”和“.bashrc”区别的总结

输出和输出

输出echo

echo用于字符串的输出,类似于PHP中的echo

  • echo特点:
    • 输出的字符串,可以省略单双引号
    • 可以显示转义符
    • 可以显示变量
    • 可以显示换行
    • 可以显示命令执行结果
#!/bin/bash

# 字符串的单双引号都是可以省略的
echo "你好"
echo '你好'
echo 你好

# 显示转义符
echo \"你好,转义符\"

# 可以显示变量
# 注意:变量名和等号之间不能有空格 也就是:变量名=变量值
name="小峰哥"
echo "我是:"$name 

# 显示换行 echo 后面添加参数-e
echo -e "换\n行"

# echo默认是换行的,不换行需要添加参数-e,后面跟上\c
echo -e "不换行\c"
echo "===="

# 原样输出,是单引号
echo '"我是:"$name '

# 显示执行结果
echo `date`

# 输出的结果是:
你好
你好
你好
"你好,转义符"
我是:小峰哥
换
行
不换行====
"我是:"$name
2019年 1月20日 星期日 02时59分27秒 CST
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39

输出printf

printf也是输出目录,但是比echo更加强大,类似C语言的printf函数

  • printf 由 POSIX 标准所定义,使用 printf 的脚本比使用 echo 移植性好
  • printf 使用引用文本或空格分隔的参数,外面可以在 printf 中使用格式化字符串,还可以制定字符串的宽度、左右对齐方式等
  • 默认 printf 不会像 echo 自动添加换行符,我们可以手动添加 \n
printf  format-string  [arguments...]
1
  • format-string: 格式控制字符串
  • arguments: 参数列表
printf "你好,%s ,我是:%s\n" '小峰哥' 'xiaofengge'
# 你好,小峰哥 ,我是:xiaofengge

printf "%-5s %-10s %-4s\n" Num Name weight     # 三个%分别对应后面的三个参数
printf "%-5s %-10s %-4.2f\n" 1 Tom   101.1     # 减号“-”表示左对齐
printf "%-5s %-10s %-4.2f\n" 2 Marry 87.765    # 5s表示第一个参数占用5个字符
printf "%-5s %-10s %-4.2f\n" 3 Bob   46

# 输出的结果:
Num   Name       weight
1     Tom        101.10
2     Marry      87.77
3     Bob        46.00
1
2
3
4
5
6
7
8
9
10
11
12
13

TIP

printf只是格式化输出,不会改变任何结果,所以在格式化浮点数的输出时,浮点数结果是不变的,仅仅只是改变了显示的结果

printf转义序列

序列 说明
\a 警告字符,通常为ASCII的BEL字符
\b 后退
\c 抑制(不显示)输出结果中任何结尾的换行字符(只在%b格式指示符控制下的参数字符串中有效),而且,任何留在参数里的字符、任何接下来的参数以及任何留在格式字符串中的字符,都被忽略
\f 换页(formfeed)
\n 换行
\r 回车(Carriage return)
\t 水平制表符
\v 垂直制表符
\ 一个字面上的反斜杠字符
\ddd 表示1到3位数八进制值的字符。仅在格式字符串中有效
\0ddd 表示1到3位的八进制值字符

忽略无关输出

黑洞设备/dev/null

  • 相当于只能写入,不能读出的单向文件
  • 存放到其中的数据都会丢失
  • 用法:可执行语句 &> /dev/null
#!/bin/bash

echo "11"
# 这句话不会输出,因为被忽略了
echo "12" &> /dev/null
echo "13"

1
2
3
4
5
6
7

TIP

很多时候,许多输出我们其实是不关心的,他们的输出其实有时候是一种干扰,所以我们可以用这种方法,忽略无关输出

输入和输出重定向

  • 一个命令通常从一个叫标准输入的地方读取输入,默认情况下,这恰好是你的终端
  • 同样,一个命令通常将其输出写入到标准输出,默认情况下,这也是你的终端

TIP

也可以说:标准输入设备指的是键盘,标准输出设备指的是显示器

标准输入输出设备

  • 在 Linux 中,所有的内容都是文件,计算机硬件也是文件,标准输入设备(键盘)和标准输出设备(显示器)也是文件
  • Linux 是使用设备文件名来表示硬件的(比如 /dev/sda1 就代表第一块 SATA 硬盘的第一个主分区),但是键盘和显示器的设备文件名并不好记忆,我们用"0"、"1"、"2"来分别代表标准输入、标准输出和标准错误输出
  • 输出重定向指的是改变输出方向,不再输出到屏幕上,而是输出到文件他设备中
  • 输入重定向则是指不再使用键盘作为输入设备,而是把文件的内容作为命令的输入
设 备 设备文件名 文件描述符 类 型
键盘 /dev/stdin 0 标准输入
显示器 /dev/stdout 1 标准输出
显示器 /dev/stderr 2 标准错误输出

重定向命令列表

命令 说明
command > file 将输出重定向到 file。
command < file 将输入重定向到 file。
command >> file 将输出以追加的方式重定向到 file。
n > file 将文件描述符为 n 的文件重定向到 file。
n >> file 将文件描述符为 n 的文件以追加的方式重定向到 file。
n >& m 将输出文件 m 和 n 合并。
n <& m 将输入文件 m 和 n 合并。
<< tag 将开始标记 tag 和结束标记 tag 之间的内容作为输入。

输出重定向

输出重定向指的是把命令的结果不再输出到屏幕中,而是输出文件中

  • 一般情况下,每个 Linux 命令运行时都会打开三个文件:
    • 标准输入文件(stdin):stdin的文件描述符为0,Unix程序默认从stdin读取数据
    • 标准输出文件(stdout):stdout 的文件描述符为1,Unix程序默认向stdout输出数据
    • 标准错误文件(stderr):stderr的文件描述符为2,Unix程序会向stderr流中写入错误信息

输出重定向命令格式

命令(command) > 文件(file)
1
  • ">" 代表的是覆盖
  • ">>" 代表的是追加

Bash 支持的输出重定向符号

类 型 符 号 作 用
标准输出重定向 命令 > 文件 以覆盖的方式,把命令的正确输出输出到指定的文件或设备中
命令 >> 文件 以追加的方式,把命令的正确输出输出到指定的文件或设备中
标准错误输出重定向 错误命令2 > 文件 以覆盖的方式,把命令的错误输出输出到指定的文件或设备中
错误命令2 >> 文件 以追加的方式,把命令的错误输出输出到指定的文件或设备中
正确输出和错误输出同时保存 命令 > 文件2>&1 以捜盖的方式,把正确输出和错误输出都保存到同一个文件中
命令 >> 文件2>&1 以追加的方式,把正确输出和错误输出都保存到同一个文件中
命令&>文件 以覆盖的方式,把正确输出和错误输出都保存到同一个文件中
命令&>>文件 以追加的方式,把正确输出和错误输出都保存到同一个文件中
命令>>文件1 2>>文件2 把正确的输出追加到文件1中,把错误的输出追加到文件2中
# 将ls -al的目录输出结果到1.log文件中
ls -al > 1.log

# cat查看1.log文件内容
cat 1.log
total 17784
drwxr-xr-x+  75 huangxuefeng  staff     2400  1 20 23:58 .
drwxr-xr-x    6 root          admin      192 11 29 22:55 ..
-rw-r--r--    1 huangxuefeng  staff        0  1 20 23:58 1.log
drwxr-xr-x    4 huangxuefeng  staff      128 12 12  2017 AndroidStudioProjects
drwxr-xr-x    3 huangxuefeng  staff       96 11  4  2017 Application Data
drwx------    7 huangxuefeng  staff      224  6 16  2018 Applications
drwx------@   5 huangxuefeng  staff      160 11 24 06:05 Applications (Parallels)
drwx------+  40 huangxuefeng  staff     1280  1 20 02:40 Desktop
drwx------+  18 huangxuefeng  staff      576 12 21 22:06 Documents
drwx------+ 270 huangxuefeng  staff     8640  1 20 01:09 Downloads
drwx------@  82 huangxuefeng  staff     2624  1  6 23:35 Library
drwx------+  11 huangxuefeng  staff      352  7  9  2018 Movies
drwx------+  11 huangxuefeng  staff      352  7  9  2018 Music
drwxr-xr-x    4 huangxuefeng  staff      128  6 10  2018 Parallels
drwx------+  10 huangxuefeng  staff      320  7  9  2018 Pictures
drwxr-xr-x+   5 huangxuefeng  staff      160 10  8  2017 Public
drwxr-xr-x    3 huangxuefeng  staff       96 12 29 00:13 PycharmProjects
drwxrwxrwx    3 root          staff       96  7  3  2018 Sites
drwxr-xr-x    2 huangxuefeng  staff       64  6 26  2018 VirtualBox VMs
drwxr-xr-x   23 huangxuefeng  staff      736  1  6 23:54 anaconda3
-rw-r--r--    1 huangxuefeng  staff    36864  4 25  2018 ipmsg.db
drwxr-xr-x   17 huangxuefeng  staff      544  6  4  2018 我的文件

# 连续支持2次pwd,并且将结果追加到2.log文件中
pwd >> 2.log;pwd >> 2.log
cat 2.log
# 结果
/Users/xiaofengge

# 输出错误重定向
# 注意这里必须是2>> 不添加2是不行的
ls test 2>> err.log
cat err.log
# 结果
ls: test: No such file or directory

# 正确输出和错误输出同时保存
# 下面2个命令,哪个都一样
ls test >> 3.log 2>&1
# 这句话,我执行的时候,失败了!!!!
# ls test &>>3.log

cat 3.log
# 结果
ls: test: No such file or directory
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51

TIP

我们推荐把正确输出和错误输出分开保存到不同的文件中

# ls命令执行的正确结果,输入到list.log文件,如果发生错误,错误输出到err.log文件中
ls >>list.log 2>>err.log
1
2

输入重定向

输入重定向是改变输入的方向,不再使用键盘作为命令的输入,而是使用文件作为命令的输入

wc(Word Count)命令

统计指定文件中的字节数、字数、行数,并将统计结果显示输出

  • 统计指定文件中的字节数、字数、行数,并将统计结果显示输出
  • 该命令统计指定文件中的字节数、字数、行数
  • 如果没有给出文件名,则从标准输入读取
  • wc同时也给出所指定文件的总统计数
#wc [选项] [文件名]
1
  • 选项
    • -c 统计字节数
    • -l 统计行数
    • -m 统计字符数。这个标志不能与 -c 标志一起使用
    • -w 统计字数。一个字被定义为由空白、跳格或换行字符分隔的字符串
    • -L 打印最长行的长度
    • -help 显示帮助信息
    • --version 显示版本信息
wc anaconda3/org.freedesktop.dbus-session.plist
# 结果
      33      49     752 anaconda3/org.freedesktop.dbus-session.plist
      
# << : 重定向符号
# 使用字符关键字作为命令输入的结束,而不使用 Ctrl+D 快捷键

# 指定hello为结束命令,把我们键盘输入的字符串写入1.log文件中
wc << 'hello' > 1.log
> nihao
> woshixiaofengge
> hello

# 查看1.log文件
cat 1.log 

# 结果
       2       2      22
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

TIP

"<<"之后的关键字可以自由定义,只要再碰到相同的关键字,两个关键字之间的内容将作为命令的输入

注意:内容不包括关键字本身

多命令执行

我们有时候需要多条命令安装一定的顺序执行,Shell中提供了一定的机制

Shell中提供了三种(加上管道是四种)多命令执行机制

多命令执行符 格 式 作 用
;(分号) 命令1 ; 命令2 多条命令顺序执行,命令之间没有任何逻辑关系
&& 命令1 && 命令2 如果命令1正确执行($?=0),则命令2才会执行 如果命令1执行不正确($?≠0),则命令2不会执行
II 命令1 || 命令2 如果命令1执行不正确($?≠0),则命令2才会执行 如果命令1正确执行($?=0),则命令2不会执行

分号";"

用分号连接的多条命令,会一次全部执行,并且命令之间没有任何关系,互不干扰

ls;pwd;mkdir a.txt;vim a.txt
1

TIP

不论前一条命令是否正确执行,都不影响后续命令的执行

逻辑与"&&"

只有第一条命令正确执行了,"&&"连接的第二条命令才会执行,这样可以保证所有的命令执行完毕后,执行过程都是成功的

cd ./a.txt && pwd
# 第二个命令不会执行,因为a.txt没有个目录,第二个命令不会执行
1
2

TIP

命令 2 是如何知道命令 1 正确执行了呢?

这就需要 Bash 的预定义变量 $? 的支持了,如果 $? 返回值是 0,则证明上一条命令正确执行;如果 $? 返回值是非 0,则证明上一条命令执行错误

逻辑或"||"

使用"||"连接多条命令,则只有前一条命令执行错误,后一条命令才能执行

cd ./a.txt || pwd
# 先报错,因为第一个目录会执行错误
-bash: cd: ./a.txt: No such file or directory
# 第一个命令执行错误,第二个命令才会执行
/Users/xxx
1
2
3
4
5

grep

  • grep命令用于查找文件里符合条件的字符串
  • 若不指定任何文件名称,或是所给予的文件名为"-",则grep指令会从标准输入设备读取数据
grep [选项] "搜索内容" 文件名
1

grep选项参考

  • grep选项参考

  • -A 数字:列出符合条件的行,并列出后续的 n 行

  • -B 数字:列出符合条件的行,并列出前面的 n 行

  • -c:统计找到的符合条件的字符串的次数

  • -i:忽略大小写

  • -l:只列出匹配的文件名

  • -L:列出不匹配的文件名

  • -w:只匹配整个单词,而不是字符串的一部分

  • -C number:匹配的上下文分别显示[number]行

  • -n:输出行号

  • -v:反向査找

  • --color=auto:搜索出的关键字用颜色显示

  • grep pattern1 | pattern2:显示匹配 pattern1 或 pattern2的行

  • grep pattern1 files | grep pattern2:显示既匹配 pattern1 又匹配pattern2 的行

grep 'a' ./
grep: ./: Is a directory

grep 'a' ./*
# 搜索全部文件的话用
# 这里也是全部报错,目录是会报错的:Is a directory
1
2
3
4
5
6
  • 默认情况下,‘grep’只搜索当前目录,如果此目录下有许多子目录,‘grep’会以如下形式列出: grep: sound: Is a directory
  • 解决办法:
    • 明确要求搜索子目录:grep -r
    • 忽略子目录:grep -d skip

TIP

grep匹配默认是区分大小写的

用于搜索的特殊符号

标注单词的开始与结尾

  • \< :标记单词的开头
  • \>:标记单词的结尾
grep man * 
# 会匹配 'Batman、'manic'、'man'等

grep '\<man' * 
# 匹配'manic'和'man',但不是‘Batman’ 

grep '\<man\>' 
# 只匹配'man',而不是'Batman'或'manic'等其他的字符串
1
2
3
4
5
6
7
8

字符串在行首和行尾

  • ^:匹配的字符串在行首
  • $:匹配的字符串在行尾
grep -n “^$” a.txt
# 返回结果 2
# 说明第二行是空行

grep -n “^123” a.txt 
#查询以123开头的行

grep -n “abc$” a.txt 
#查询以abc结尾的行
1
2
3
4
5
6
7
8
9

TIP

grep '^$' file 可以匹配空行

查询有特殊含义的字符

查询诸如$ . ‘ ” * [] ^ | \ + ? ,必须在特定字符前加\

grep “\.” a.txt
# 在a.txt中查询包含”.”的所有行

grep “my\.conf” a.txt 
# 查询有文件名my. conf的行
1
2
3
4
5

find

用来在指定目录下查找文件

find 路径 参数 [-print -exec -ok ..]
1

路径:

  • find 命令查找的目录路径
  • ./ 表示当前目录
  • / 表示系统根目录

参数:

  • -name:按照文件名查找文件
  • -mtime -n +n:按照文件的更改时间来查找文件,-n 表示文件更改时间在 n 天之内,+n 表示文件更改时间在 n 天之外
  • -newer file1:查找比文件 file1 新(即更改时间晚)的文件
  • -type:查找某一类型的文件
    • d - 目录
    • f - 普通文件
    • b - 块设备文件
    • c - 字符设备文件
    • p - 管道文件
    • l - 符号链接文件
  • -size n:
    • 查找大小为 n 的文件
    • 末尾带有 c 时表示文件大小以字节计,带 k 时表示文件大小以 KB 计,以此类推
# 在当前目录与子目录下查找txt后缀的文件
find ./ -name "*.txt"

# 查找在当前目录下2天内修改的文件
find ./ -mtime -2

# 查找当前目录下比1.txt新的文件
find ./ -newer 1.txt

# 在当前目录查找所以目录文件
find ./ -type d

# 查找当前目录下大小大于10k的文件
find ./ -size +10000c
1
2
3
4
5
6
7
8
9
10
11
12
13
14

参数后参数

  • -options:指定 find 命令的常用选项
  • -print:find 命令将匹配的文件输出到标准输出
  • -exec:find 命名对匹配的文件执行该参数所给出的 shell 命令
  • -ok:与 -exec 类似,只不过在执行每一个命令之前都会给出提示,让用户决定是否执行
  • -xargs:与 -exec 类似,对 find 命名匹配的文件执行该参数所给出的 shell 命令,并且效率更高
# 查找当前目录下所有文件并输出文件类型
find . -type f -print | xargs file 

# 查找当前目录下所有txt文件并将结果输出到txt.log文件,一行输出一个结果
find . -name "*.txt" -print | xargs -n1 > /e/txt.log

# 查找当前目录下的所有文件并在这些文件中搜索add_experience并将结果输出到文件
find . -type f | xargs grep "add_experience" > /f/add_experience.txt

# 删除3天以前的所有文件和文件夹
find ./ -mtime +3 -print | xargs rm -f -r

# 删除文件大小为0的文件
find ./ -size 0 | xargs rm -f
1
2
3
4
5
6
7
8
9
10
11
12
13
14

TIP

  • find 命令用于在系统中搜索符合条件的文件名,如果需要模糊査询,则使用通配符进行匹配,搜索时文件名是完全匹配的
  • find 命令是可以通过 -regex 选项识别正则表达式规则的,也就是说,find 命令可以按照正则表达式规则匹配,而正则表达式是模糊匹配

管道符

  • 在 Bash 中,管道符使用"丨"代表
  • 管道符也是用来连接多条命令的,如"命令1丨命令2"

管道符要求

  • 用管道符连接的命令,命令 1 的正确输出作为命令 2 的操作对象
  • 注意:命令 1 必须有正确输出,而命令 2 必须可以处理命令 1 的输出结果
  • 而且命令 2 只能处理命令 1 的正确输出,而不能处理错误输出
ps -f | grep npm
# ps 显示瞬间进程的状态,并不动态连续
# | grep npm 对ps的输出,进行查询 包含npm字符串的进行输出
# 结果
501  4176  3808   0  1:08上午 ttys000    0:00.27 npm   
501  4529  4228   0  1:28上午 ttys001    0:00.00 grep npm
1
2
3
4
5
6