Linux which whereis locate grep find
概览

  1. which : 查看执行文件的位置。
  2. whereis : 查看可执行文件位置和相关文件。
  3. locate : 配合数据库缓存,快速查看文件的位置。
  4. grep : 过滤匹配,他是一个文件搜索工具。
  5. find : 可以根据条件查看文件。

which

在 PATH 变量中定义的全部路径中查找可执行文件或脚本
which 命令有两个重要参数:

  • -all, -a 默认情况下,which 命令会在匹配到第一个结果后结束运行,添加该参数可以让其搜索所有路径。
  • -read-alias, -i 将输入视为别名搜索。Linux 系统中通常会使用 alias 设置诸多别名来简写命令,例如 Centos 中的 ll 实际是 ls -l ,而 whichalias | /usr/bin/which --tty-only --read-alias --show-dot --show-tilde

    # Centos
    # 以绝对路径调用 which,这样就不会受到 Centos 默认的几个参数影响
    # 返回结果说明找不到 ll 命令
    $ /usr/bin/which ll
    /usr/bin/which: no ll in (/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin)
    # 直接输入 which 时实际效果为带有“默认参数”的
    # 返回结果说明 ll 是 ls -l 的别名,
    $ which ll
    alias ll='ls -l --color=auto'
          /usr/bin/ls
    
  • which ll 相当于 alias | /usr/bin/which --tty-only --read-alias --show-dot --show-tilde ll,返回结果第一行是 alias 输出的 ll 别名设置情况,第二行则是 ls 的实际位置。

which 的其他几个参数如下:

  • --tty-only:尽在终端调用的情况下附带右侧添加的参数,其他情况下不接收右侧其他参数(此处的参数值 --show-dot--show-tilde 此类,输入的待查询命令仍然会接收),通过这个命令可以保证 Shell 脚本中的 which 命令正确执行。
  • --show-dot:输出以 “.” 符号开头的目录。Linux 中 “.“ 符号开头的目录是约定的隐藏文件夹,没有该参数时会忽略这些目录。
  • --show-tilde:将用户家目录替换成 “~” 符号输出。Linux 中 “~“ 符号是登录用户家目录的缩写,如果登录用户名为 cncsl,则 “~” 指 “/home/cncsl” 目录。当使用 root 账号登录时该参数无效。

    --all, -a      显示所有的匹配路径
    

    image.png
    操作:

    ➜  / which pwd
    /usr/bin/pwd
    

    image.png

    whereis

    查找指定命令的可执行文件、源代码和手册的位置。

    $ whereis vim
    vim: /usr/bin/vim /usr/share/vim /usr/share/man/man1/vim.1.gz
    

    可以看出,vim 的可执行程序位于 /usr/bin/vim,手册位于 /usr/share/vim/share/man/man1/vim.1.gz 目录。

  • -b-m-s 分别用于指定仅查询可执行文件、手册和源代码。

  • -B-M-S 命令用于指定查询路径。
  • -u 参数的描述直译为仅查询有异常情况的命令。所谓的异常情况是指,某个命令的相关类型文件不止恰好一份(一份都没有或多于一份)。例如:

    • ls 命令具有两份手册:

      $ whereis -m -u ls
      ls: /usr/share/man/man1/ls.1.gz /usr/share/man/man1p/ls.1p.gz
      
    • Linux 系统中有很多个与 python 相关的可执行文件:

      $ whereis -b -u python
      python: /usr/bin/python /usr/bin/python2.7 /usr/lib/python2.7 /usr/lib64/python
      
一般不加参数使用
-b         只搜索二进制文件
-B <目录>  定义二进制文件查找路径
-m         只搜索 man 手册
-M <目录>  定义 man 手册查找路径
-s         只搜索源代码
-S <目录>  定义源代码查找路径

操作:

➜  / whereis ls
ls: /usr/bin/ls /usr/share/man/man1/ls.1.gz

image.png

locate

在文档和目录名称的数据库中查找指定文件。
Linux 系统会定期自动扫描磁盘来维护一个记录磁盘数据的数据库,而 locate 命令使用的数据库是 /var/lib/mlocate/mlocate.db

$ ls -hl /var/lib/mlocate/mlocate.db
-rw-r-----. 1 root slocate 2.7M Feb  4 03:42 /var/lib/mlocate/mlocate.db

可以看出当前 mlocate.db 文件共记录了 2.7M 的数据。

  • --count, -c :不输出具体的文件路径信息,仅输出查询到的数量。
  • --ignore-case, -i:查询时忽略大小写
  • --limit, -l, -n LIMIT:限定输出的文件数量为 LIMIT
  • --regexp,-r REGEXP:使用 REGEXP 指定的正则表达式匹配。

    # 统计有多少PNG格式的图像文件
    $ locate -c png
    # 统计有多少 readme 文件(根据编写者的习惯,readme 文件可能名为 README、ReadMe等)
    $ locate -c -i readme
    # 输出十个 .gz 归档文件的路径
    $ locate -l 10 *.gz
    # 查看 tomcat 2021年1月的日志
    $ locate -r tomcat.2021-01-[0-3][0-9].log
    

    由于 locate 命令是从数据库查找文件,新创建的文件可能由于未被记录到数据库中而无法查询到,这种时候需要使用 updatedb 命令手动更新数据库。
    操作: locate和find命令功能差不多,但是搜索效率更高,因为locate查的是数据库而find查找的是目录文件。
    数据库:

    ➜  ~ ls /var/lib/mlocate/mlocate.db
    /var/lib/mlocate/mlocate.db
    

    相关配置文件:

    ➜  ~ ls /etc/updatedb.conf
    /etc/updatedb.conf
    

    相关定时任务:

    ➜  ~ ls /etc/cron.daily/mlocate
    /etc/cron.daily/mlocate
    

    举例:

    ➜  ~ touch shafa
    ➜  ~ locate shafa
    ➜  ~ updatedb
    ➜  ~ locate shafa
    /root/shafa
    

    :::tips 注:如果当天新建的文件查找,需要手动updatedb。 :::

    grep

    命令:grep
    语法:grep 参数 目标值 文件
    与 grep 相似的工具还有 egrepfgrep,实用性并不强,其功能完全可以通过 grep 的扩展参数来实现。

    常用参数

  • -A:除了匹配行,额外显示该行之的N行

  • -B:除了匹配行,额外显示该行之的N行
  • -C:除了匹配行,额外显示该行前后的N行
  • -c:统计匹配的行数
  • -e实现多个选项间的逻辑 or 关系
  • -E支持扩展的正则表达式
  • -F:相当于 fgrep
  • -i忽略大小写
  • -n:显示匹配的行号
  • -o:仅显示匹配到的字符串
  • -q:安静模式,不输出任何信息,脚本中常用
  • -s:不显示错误信息
  • -v显示不被匹配到的行
  • -w:显示整个单词
  • --color:以颜色突出显示匹配到的字符串
    -v       取反
    -i       忽略大小写
    -n       输出的同时打印行号
    ^*       以*开头
    *$       以*结尾
    ^$       空行
    

    操作

    查 /etc/passwd有root的行

    ➜  / grep root /etc/passwd
    root:x:0:0:root:/root:/bin/zsh
    operator:x:11:0:operator:/root:/sbin/nologin
    dockerroot:x:996:993:Docker User:/var/lib/docker:/sbin/nologin
    
    image.png

    查 /etc/passwd 没有root的行(内容较多,仅展示几行)

    ➜  / grep -v root /etc/passwd
    bin:x:1:1:bin:/bin:/sbin/nologin
    daemon:x:2:2:daemon:/sbin:/sbin/nologin
    adm:x:3:4:adm:/var/adm:/sbin/nologin
    lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
    sync:x:5:0:sync:/sbin:/bin/sync
    shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
    halt:x:7:0:halt:/sbin:/sbin/halt
    mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
    games:x:12:100:games:/usr/games:/sbin/nologin
    ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
    nobody:x:99:99:Nobody:/:/sbin/nologin
    systemd-bus-proxy:x:999:998:systemd Bus Proxy:/:/sbin/nologin
    systemd-network:x:192:192:systemd Network Management:/:/sbin/nologin
    dbus:x:81:81:System message bus:/:/sbin/nologin
    polkitd:x:998:997:User for polkitd:/:/sbin/nologin
    tss:x:59:59:Account used by the trousers package to sandbox the tcsd daemon:/dev/null:/sbin/nologin
    sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
    postfix:x:89:89::/var/spool/postfix:/sbin/nologin
    chrony:x:997:995::/var/lib/chrony:/sbin/nologin
    ntp:x:38:38::/etc/ntp:/sbin/nologin
    nscd:x:28:28:NSCD Daemon:/:/sbin/nologin
    tcpdump:x:72:72::/:/sbin/nologin
    mysql:x:995:1000::/home/mysql:/bin/bash
    
    image.png

    查 /etc/passwd 有root的行并显示行号

    ➜  / grep -n root /etc/passwd
    1:root:x:0:0:root:/root:/bin/zsh
    10:operator:x:11:0:operator:/root:/sbin/nologin
    25:dockerroot:x:996:993:Docker User:/var/lib/docker:/sbin/nologin
    
    image.png
    grep forest f.txt     #文件查找
    grep forest f.txt cpf.txt #多文件查找
    grep 'log' /home/admin -r -n #目录下查找所有符合关键字的文件
    cat f.txt | grep -i shopbase    
    grep 'shopbase' /home/admin -r -n --include *.{vm,java} #指定文件后缀
    grep 'shopbase' /home/admin -r -n --exclude *.{vm,java} #反匹配
    seq 10 | grep 5 -A 3    #上匹配
    seq 10 | grep 5 -B 3    #下匹配
    seq 10 | grep 5 -C 3    #上下匹配,平时用这个就妥了
    cat f.txt | grep -c 'SHOPBASE'
    

    把包含 syslog 的行过滤出来

    ```bash $ grep “syslog” g.txt syslog:x:104:108::/home/syslog:/bin/false

可以忽略大小写

$ grep -i “SYSLOG” g.txt syslog:x:104:108::/home/syslog:/bin/false

<a name="ZylIv"></a>
#### 把以 ntp 开头的行过滤出来
```bash
$ grep "^ntp" g.txt
ntp:x:108:114::/home/ntp:/bin/false

# 把false结尾的行过滤出来
$ grep "false$" g.txt
syslog:x:104:108::ntp.syslog:/bin/false
ntp:x:108:114::/home/ntp:/bin/false

把匹配 ntp 的行以及下边的两行过滤出来

$ grep -A2 "syslog" g.txt
syslog:x:104:108::ntp.syslog:/bin/false
ntp:x:108:114::/home/ntp:/bin/false
sshd:x:109:65534::sshd:/usr/sbin/nologin

把包含 syslog 及上边的一行过滤出来

$ grep -B1 "syslog" g.txt
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
syslog:x:104:108::ntp.syslog:/bin/false

把包含 syslog 以及上、下一行内容过滤出来

$ grep -C1 "syslog" g.txt
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
syslog:x:104:108::ntp.syslog:/bin/false
ntp:x:108:114::/home/ntp:/bin/false

过滤某个关键词,并输出行号

$ grep -n "ntp" g.txt
3:syslog:x:104:108::ntp.syslog:/bin/false
4:ntp:x:108:114::/home/ntp:/bin/false

过滤不包含某关键词,并输出行号

$ grep -n -v "sbin" g.txt
1:0root:x:0:0:root:/root:/bin/zsh
3:syslog:x:104:108::ntp.syslog:/fnlas
4:ntp:x:108:114::/home/ntp:/bin/false

删除掉空行

$ grep -v "^$" g.txt
# "^$"表示空行

过滤包含 root 或 syslog 的行

# 用"-e"实现多选项间逻辑or关系
$ grep -e "root" -e "syslog" g.txt
0root:x:0:0:root:/root:/bin/zsh
syslog:x:104:108::ntp.syslog:/bin/false

# 等效于
$ grep -E "root|syslog" g.txt

查看当前目录中包含某关键词的所有文件(这个很有用)

# -r 表示在当前目录递归查询
$ grep -r "font" .
./README.md: --pdf-mono-font-size 12
./default.css:  font-size: 120%;
./default.css:  font-weight: bold;
./ samples/foo/genmobi.sh:  --default-font 12

# 一般会用下边的命令,会更加有效(显示行号,且以单词严格匹配)
$ grep -rnw "font" .

# 在递归的过程中排除某些目录
$ grep -rnw --exclude-dir={.git,svn} "mail"

grep命令的其他操作

grep -H 'spring' *.xml 查找所以有的包含spring的xml文件
grep 'test' d* 显示所有以d开头的文件中包含test的行。
grep 'test' aa bb cc 显示在aa,bb,cc文件中匹配test的行。
grep '[a-z]\{5\}' aa 显示所有包含每个字符串至少有5个连续小写字符的字符串的行。

find

在一个目录层级中查找文件。
find 命令功能强大,可根据多种条件查询文件,随后进行自定义的操作,格式如下:

find [path...] [expression]
  • find 会实际的扫描磁盘,所以速度会明显小于前三个。

命令:find
语法:find 路径 参数 输出
查找路径:指定具体目标路径;默认为当前目录
查找条件:指定的查找标准,可以文件名、大小、类型、权限等标准进行;默认找出指定路径下的所有文件
处理动作:对符合条件的文件做操作,默认输出至屏幕

查找条件

指搜索层级

-maxdepth level 最大搜索目录深度,指定目录为第1级
-mindepth level 最小搜索目录深度

先处理目录内的文件,再处理目录

-depth

根据文件名和inode查找

-name“文件名称”:支持使用glob
*,?,[],[^]
-iname“文件名称”:不区分字母大小写
-inum n 按inode号查找
-samefile name 相同inode号的文件
-links n 链接数为n的文件
-regex “PATTERN”:以PATTERN匹配整个文件路径,而非文件名称

根据属主、属组查找

-user USERNAME:查找属主为指定用户(UID)的文件
-group GRPNAME:查找属组为指定组(GID)的文件
-uid UserID:查找属主为指定的UID号文件
-gid GroupID:查找属组为指定的GID号的文件
-nouser:查找没有属主的文件
-nogroup:查找没有属组的文件

根据文件类型查找

type TYPE:
f:普通文件
d:目录文件
l:符号链接文件
s:套接字文件
b:块设备文件
c:字符设备文件
p:管道文件

空文件或目录

-empty
Find/app -type d -empty

组合条件

与:-a
或:-o
非:-not,!

常用参数

路径: 例如用 . 来表示当前目录,用 / 来表示系统根目录。
-print:显示的时候”\n”做为定界符, 换行
-print0:与xargs配套使用,以“\0”做为定界符

find常用命令选项:

-name   按照文件名查找文件。“名称”
-perm   按照文件权限来查找文件。666 777 等
-depth  在查找文件时,首先查找当前目录中的文件,然后再在其子目录中查找
-user   按照文件属主来查找文件
-atime  -ctime (单位是天)
-mmin -cmin  -amin(单位是分钟)
-size n [c] 查找文件长度为n块的文件,带有c时表示文件长度以字节计
-follow  如果find命令遇到符号链接文件,就跟踪至链接所指向的文件。

操作

根据文件名称查找

find / -name filename.txt 根据名称查找/目录下的filename.txt文件。
find . -name "*.xml" 递归查找所有的xml文件

查看当前目录下文件名为.conf的文件

➜  /etc find *.conf
asound.conf
chrony.conf
dnsmasq.conf
dracut.conf
e2fsck.conf
GeoIP.conf

image.png

查看当前目录下yum.开头的文件,输出结果换行显示(默认)

➜  /etc find yum.* -print
yum.conf
yum.repos.d
yum.repos.d/CentOS-Base.repo
yum.repos.d/epel.repo
➜  /etc find yum.*
yum.conf
yum.repos.d
yum.repos.d/CentOS-Base.repo
yum.repos.d/epel.repo

image.png

查看当前目录下yum.开头的文件,输出结果不换行显示

➜  /etc find yum.* -print
yum.conf
yum.repos.d
yum.repos.d/CentOS-Base.repo
yum.repos.d/epel.repo
➜  /etc find yum.*
yum.conf
yum.repos.d
yum.repos.d/CentOS-Base.repo
yum.repos.d/epel.repo
➜  /etc find yum.* -print0
yum.confyum.repos.dyum.repos.d/CentOS-Base.repoyum.repos.d/epel.repo#

image.png
对查找的内容执行相应命令
默认执行动作 : -print
常用动作:

-exec  这个参数后可以跟自定义shell命令

操作:

查询yum.开头的文件并用ls查询其更多属性

➜  /etc find yum.* -exec ls -l {} \;
-rw-r--r--. 1 root root 970 Nov 15  2016 yum.conf
total 8
-rw-r--r-- 1 root root 675 Jul 18  2019 CentOS-Base.repo
-rw-r--r-- 1 root root 230 Jul 18  2019 epel.repo
-rw-r--r-- 1 root root 675 Jul 18  2019 yum.repos.d/CentOS-Base.repo
-rw-r--r-- 1 root root 230 Jul 18  2019 yum.repos.d/epel.repo

image.png

查询fcscanf文件并变成.bak结尾的文件

➜  /etc find fcscanf
fcscanf
➜  /etc find fcscanf -exec mv {} {}.bak \;
➜  /etc find *.bak
fcscanf.bak
nsswitch.conf.bak
➜  /etc

image.png

递归查找所有文件内容中包含hello world的xml文件

find . -name "*.xml" | xargs grep "hello world"

删除文件大小为零的文件

find ./ -size 0 | xargs rm -f &

逻辑查询

-a  并且
-o  或者
+   高于
-   低于

查看 .sh或者.q结尾的文件。

➜  test find . -name "*.sh" -o -name "*.q"
./book.q
./stop.sh
./start.sh

查看.sh结尾并且s开头的文件。

➜  test find . -name "*.sh" -a -name "s*"
./stop.sh
./start.sh

在文件中插入内容后查看。

➜  test ll
总用量 12K
-rw-r--r-- 1 root root  9 11月  4 15:10 book.q
-rw-r--r-- 1 root root 13 11月  4 15:10 start.sh
-rw-r--r-- 1 root root  4 11月  4 15:10 stop.sh
-rw-r--r-- 1 root root  0 11月  4 14:56 xq1.txt.bak
-rw-r--r-- 1 root root  0 11月  4 14:56 xq2.txt.bak
-rw-r--r-- 1 root root  0 11月  4 14:56 xq.txt.bak

查看/etc 大于40k小于50k的文件

➜  test find /etc/ -size +40k -a -size  -50k
/etc/selinux/targeted/active/modules/100/sysadm/hll
/etc/selinux/targeted/contexts/files/file_contexts.homedirs.bin

按类型和时间查询

sudo -u admin find /home/admin /tmp /usr -name \*.log(多个目录去找)
find . -iname \*.txt(大小写都匹配)
find . -type d(当前目录下的所有子目录)
find /usr -type l(当前目录下所有的符号链接)
find /usr -type l -name "z*" -ls(符号链接的详细信息 eg:inode,目录)
find /home/admin -size +250000k(超过250000k的文件,当然+改成-就是小于了)
find /home/admin f -perm 777 -exec ls -l {} \; (按照权限查询文件)
find /home/admin -atime -1  1天内访问过的文件
find /home/admin -ctime -1  1天内状态改变过的文件    
find /home/admin -mtime -1  1天内修改过的文件
find /home/admin -amin -1  1分钟内访问过的文件
find /home/admin -cmin -1  1分钟内状态改变过的文件    
find /home/admin -mmin -1  1分钟内修改过的文件
  • 查询当前目录下所有的 markdown 文档:

    $ find . -name "*.log"
    
  • 查询用户视频文件夹中大于 100M 的文件:

    $ find ~/Videos/ -size +100M
    
  • 查询用户音乐文件夹中过去七天访问过的文件:

    $ find ~/Music/ -atime -7
    
  • 查询系统中、三个月之前创建的、一个月之内没有访问过、大于 30M 的日志文件,并删除:

    find / -ctime +90 -atime +30 -size +1M -name "*.log" -delete