which
作用:显示命令的绝对路径,which 只会去系统环境变量定义的目录中去查找文件。
| 选项 | 说明 |
|---|---|
| -a | 默认在 PATH 路径中由前向后查找命令,如果查找到了,就停止匹配。使用 -a 选项将遍历所有 PATH 路径,输出所有匹配项。 |
$ which cat
/usr/bin/cat
# which 还可以显示命令别名信息
$ which ls
alias ls='ls --color=auto'
/usr/bin/ls
# shell 内置命令无法使用 which 查找
$ which for
/usr/bin/which: no for in (/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin)
whereis
作用:显示命令及其帮助手册文件的绝对路径,或者文件的绝对路径。
| 选项 | 说明 |
|---|---|
| -b | 查找可执行文件 |
| -m | 查找 man 手册 |
| -s | 查找源代码文件 |
$ whereis cat
cat: /usr/bin/cat /usr/share/man/man1/cat.1.gz
$ whereis hosts
hosts: /etc/hosts /etc/hosts.allow /etc/hosts.deny
# 文件名:后面什么都没有,代表没有查找到
$ whereis ifcfg-eth0
ifcfg-eth0:
# -b:查找可执行文件
$ whereis -b cat
cat: /usr/bin/cat
# -m:查找帮助手册文件
$ whereis -m cat
cat: /usr/share/man/man1/cat.1.gz
# -s:查找源代码文件
$ whereis -s cat
cat:
locate & updatedb
作用:快速定位文件路径。
在 Linux 系统中有一个名为 mlocate.db 的文件,其中存储了系统文件的路径信息,locate 命令不是去磁盘中查找文件,而是直接读取 mlocate.db 这个文件的信息,找到文件的路径。此命令默认没有安装。
| 命令 | 选项 | 说明 |
|---|---|---|
| locate | -c | 只打印匹配到的行数,不打印匹配到的文件信息 |
| locate | -i | 匹配时忽略大小写 |
| locate | -r | 支持基本正则表达式 |
| locate | --regex | 支持扩展正则表达式 |
| updatedb | -U | 更新指定目录下的文件路径信息到数据库文件,默认更新系统全部文件 |
| updatedb | -v | 显示命令执行的过程 |
# 安装命令对应的软件包
$ yum install -y mlocate
# 手动更新 mlocate.db 中的信息
# 此数据库会由系统定期自动更新
$ updatedb
$ locate hosts
/etc/hosts
/etc/hosts.allow
/etc/hosts.deny
/etc/selinux/targeted/active/modules/100/denyhosts
# 支持通配符
$ locate /etc/sh*
/etc/shadow
/etc/shadow-
/etc/shells
# -c:只打印匹配到的行数,不打印匹配到的文件信息
~ locate -c hosts
24
# -U:更新指定目录下的文件路径信息到数据库文件
# -v:显示命令执行的过程
~ updatedb -vU /etc
find
作用:查找文件
命令格式:
【如何处理符号链接】
有 -H、-L、-P、-D debugopts 和 -Olevel 这些选项,暂时不做介绍;
【path】
查找的目录,比如 . 代表当前目录,/ 代表系统根目录;
【options】
| 选项 | 说明 |
|---|---|
| -depth | 从指定目录下最深层的子目录开始查找 |
| -maxdepth level | 查找的最大目录层数,level 是非负整数 |
| -regextype type | 改变正则表达式的模式,默认为 emacs,还有 posix-awk、posix-basic、posix-egrep、posix-extended |
【tests】
| 选项 | 说明 |
|---|---|
| -mtime [-n|n|+n] | 按照文件的修改时间来查找文件,单位天 -n:文件修改时间距现在 n 天以内 +n:文件修改时间距现在 n 天之前 n:文件修改时间距现在 n 天 |
| -atime [-n|n|+n] | 按照文件的访问时间来查找,单位天 |
| -ctime [-n|n|+n] | 按照文件的创建时间来查找,单位天 |
| -amin | 按照文件的访问时间来查找,单位分钟 |
| -cmin | 按照文件的创建时间来查找,单位分钟 |
| -group | 按照文件所属的组查找 |
| -name | 按照文件名查找,只支持 * ? [] 等通配符 |
| -iname | 按照文件名查找,只支持 * ? [] 等通配符,忽略大小写 |
| -newer | 查找修改时间比指定文件的修改时间新的文件 |
| -nogroup | 查找没有有效用户组的文件,即该文件的组在 /etc/groups 文件中不存在 |
| -nouser | 查找没有有效用户的文件,即该文件的用户在 /etc/passwd 文件中不存在 |
| -path pattern | 指定路径,配合 -prune 参数排除指定目录 |
| -perm | 按照文件权限来查找 |
| -regex | 接正则表达式 |
| -iregex | 接正则表达式,不区分大小写 |
| -size n[cwbkMG] | 查找文件长度为 n 块的文件,带有 cwbkMG 时表示文件长度按照字节计算,默认单位 b c:1 byte w:2 bytes b:512 bytes k:1024 bytes M:1024 * 1024 bytes G:1024 * 1024 * 1024 bytes -size +100M 查找文件大小大于 100M 的文件 -size 100M 查找文件大小等于 100M 的文件 -size -100M查找文件大小小于 100M 的文件 |
| -user | 按照文件用户来查找 |
| -type | 查找指定类型的文件 b:块设备文件 c:字符设备文件 d:目录 p:管道文件 l:链接文件 f:普通文件 s:socket 文件 D:door(Solaris) |
【actions】
| 选项 | 说明 |
|---|---|
| 将匹配到的文件打印出来,默认 | |
| -delete | 删除匹配到的文件 |
| -exec | 对匹配到的文件执行该参数所给出的命令 |
| -ok | 同 -exec,但是会询问用户是否执行 |
| -prune | 使 find 命令不在指定的目录中查找 |
find 支持【逻辑运算符】
| 逻辑运算符 | 说明 |
|---|---|
| ! | 取反 |
| -a | 取交集,and |
| -o | 取并集,or |
【案例】
# 在 /var/log/ 目录下查找修改时间距离现在大于4天的以".log"结尾的文件
$ find /var/log -mtime +5 -name "*.log"
# 在当前目录下查找在两天内受过访问的文件
$ find . -atime -2
# 在当前目录下查找在两天内被修改过的文件
$ find . -mtime -5
# 查找当前目录下的所有目录
$ find . -type d
# 查找当前目录下不是目录的文件
$ find . ! -type d
# 查找/etc目录下权限为755的文件
$ find /etc -perm 755
# 查找组权限是 w,其他权限都没有的文件,即查找权限为 0020 的文件
$ find /etc -perm g=w
# 查找组权限是 w,其他权限任意的文件
$ find /etc -perm -g=w
# 查找权限为 664 的文件
$ find . -perm 664
# 查找用户和组具有读写权限,others具有读权限的文件,权限大于 664 的文件也满足条件
$ find . -perm -664
# 查找文件的属主【或者】组内成员【或者】其他人可写的文件
$ find . -perm /222
# 查找文件的属主【或者】组内成员可写的文件
$find . -perm /220
# 查找文件的属主【或者】组内成员可写的文件
$ find . -perm /u+w,g+w
# 查找文件的属主【或者】组内成员可写的文件
find . -perm /u=w,g=w
# 查找文件的属主和组内成员【都】可写的文件
$ find . -perm -220
# 查找文件的属主和组内成员【都】可写的文件
$ find . -perm -g+w,u+w
# 查找所有人都可读【and】属主、组内成员以及其他人至少有一个可以写入【and】 属主、组内成员以及其他人至少有一个不能执行的文件
$ find . -perm -444 -perm /222 ! -perm /111
# 查找所有人都可读【and】属主、组内成员以及其他人至少有一个可以写入【and】 属主、组内成员以及其他人至少有一个不能执行的文件
# u(user),g(group),o(other),a(all)
$ find . -perm -a+r -perm /a+w ! -perm /a+x
# 查找当前目录下文件大小大于 1000 字节的文件
$ find . -size +1000c
# 查找 /etc 目录下的所有文件,除了/etc/ssh 目录
$ find /etc -path /etc/ssh -a -prune -o -print
# 命令解释
# 在目录 /etc 下查找所有文件
# 如果查找到目录 /etc/ssh,就执行 -prune 选项,即忽略
# 否则就打印出来
# 以上命令可以简写(省略 -a 选项)为:
$ find /etc -path /etc/ssh -prune -o -print
# 忽略多个目录
# ()需要转义
# 注意左右括号和 -path 之间的空格是必须的
$ find /etc \( -path /etc/ssh -o -path /etc/python \) -prune -o -print
# 在当前目录下查找 root 用户的文件
$ find . -user root
# 在当前目录下查找无效用户的文件
$ find . -nouser
# 在当前目录下查找用户组为 nobody 的文件
$ find . -group nobody
# 修改用户属组为555
$ chown .555 file.txt
# 在当前目录下查找没有有效用户组的文件
$ find . -nogroup
# 在当前目录下查找修改时间比文件 file.txt 新的文件
$ find . -newer file.txt
# 在当前目录下查找修改时间比 file1.txt 新但比 file2.txt 旧的文件
$ find . -newer file1.txt ! -newer file2.txt
# 指定查找深度
~ tree
.
├── a
│ ├── a.txt
│ └── b
│ └── a.txt
└── a.txt
$ find . -maxdepth 1 -name a.txt
./a.txt
$ find . -maxdepth 2 -name a.txt
./a.txt
./a/a.txt
$ find . -maxdepth 3 -name a.txt
./a.txt
./a/b/a.txt
./a/a.txt
# 查询深度为 1 并且文件类型为目录并且目录名不是"."的文件
$ find . -maxdepth 1 -type d ! -name "."
# 查询 深度为1 && ((文件类型是目录 && 目录名不是".") || 文件名是"a.txt") 的文件
$ find . -maxdepth 1 -type d ! -name "." -o -name "a.txt"
# 在根目录下查找名为 "find" 的文件
$ find / -regex "find"
# 在根目录下查找文件名中包含 "find" 字符串的文件
$ find / -regex ".*find"
# 指定正则表达式的类型
$ find . -regextype "posix-egrep" -name '*[0-9]'
# find命令的结果给到其他命令
# 命令格式:find path options -exec command {} \;
# 其中 {} \; 是固定写法
# {} 代表 find 命令执行后的所有文件
$ find . -type f -exec ls -l {} \;
# 删除修改时间在14天之前的文件
$ find . -type f -mtime +14 -exec rm {} \;
# 删除修改时间在14天之前的文件,删除之前逐个询问是否删除,输入 y 代表删除,输入 n 代表不删除
$ find . -type f -mtime +14 -ok rm {} \;
# 删除匹配到的文件
$ find . -name "a.txt" -delete
xargs
作用:将标准输入转换成命令行参数
| 选项 | 说明 |
|---|---|
| -n | 指定每行最大参数个数 n,可以将标准输入的文本划分为多行,每行 n 个参数,默认空格分隔 |
| -d | 自定义分隔符 |
| -i | 以{}代表前面的结果 |
| -I | 指定一个符号代表前面的结果,而不是使用 -i 默认的 {} |
| -p | 提示让用户确认是否执行后面的命令,y 执行,n 不执行 |
| -0 | 用 null 代替空格作为分隔符,配合 find 命令的 -print 选项的输出使用 |
$ cat a.txt
1 2 3 4 5 6
7 8 9
$ xargs < a.txt
1 2 3 4 5 6 7 8 9
# -n:指定每行的输出
$ xargs -n 3 < a.txt
1 2 3
4 5 6
7 8 9
# -d:自定义分隔符
$ echo aXaXaX
aXaXaX
$ echo aXaXaX |xargs -d X
a a a
$ echo aXaXaX |xargs -d X -n 2
a a
a
# 查找文件并显示详细属性
$ find . -type f | xargs ls -l
# 测试 -I 选项
$ touch file{1..9}.log
$ mkdir dir1
$ find . -name "file*log" | xargs -i mv {} dir1
$ ls dir1
file1.log file2.log file3.log file4.log file5.log file6.log file7.log file8.log file9.log
$ mkdir dir2
$ find dir1 -name "file*log" | xargs -I [] cp [] dir2
$ ls dir2
file1.log file2.log file3.log file4.log file5.log file6.log file7.log file8.log file9.log
# 创建带有空格的文件
$ touch "hello world.txt"
# 或者
$ touch hello\ world.txt
# 删除"hello world.txt"
# xargs 默认认为空格是分隔符
$ find . -name "hello world.txt" | xargs rm
rm: cannot remove ‘./hello’: No such file or directory
rm: cannot remove ‘world.txt’: No such file or directory
# -0:设置分隔符为 null
# -print0:去除文件名后的换行符号
$ find . -name "hello world.txt" -print0 | xargs -0 rm
# -p:询问是否执行后面的命令,y 代表执行,n 代表不执行
$ find . -type f | xargs -p rm
find + xargs 的执行原理:
find . -type f | xargs ls -l
首先 find 命令找到一些符合条件的文件,比如:
a.txt
b.txt
然后 xargs 命令将找到的文件名转换行成一行内容:
a.txt b.txt
将转换后的一行内容加到 xargs 之后的命令之后:
ls -l a.txt b.txt
所以执行 find . -type f | xargs mv /dir 命令会报错,因为实际执行的命令是:
mv /dir a.txt b.txt
所以需要这样执行:
# 方法一:使用 xargs 的选项
find . -type f | xargs -i mv {} /dir
# 方法二:使用 xargs 的命令的选项
# mv -t /dir:指明目标目录是 /dir
find . -type f | xargs mv -t /dir
说明:
-
xargs 之后 执行的命令会使用原始命令而不使用别名,所以 xargs 之后的 rm 命令可以不加选项 -f
-
find命令结合exec和xargs使用的区别:
-
执行效率:find 命令将查找到的文件逐个传递给 -exec 参数来执行,查到一个传递一个,如果查找到的文件较多,则执行效率较慢;xargs 命令将在 find 命令执行结束之后统一处理所有查找到的文件,效率较高,所以打包的时候,一定要使用 xargs 命令才能将多个文件打包在一起,否则包中只有最后一个文件;
-
特殊字符处理:查找到的文件名中如果包含特殊字符比如空格,-exec 命令会照常处理;而使用 xargs 命令处理带特殊字符的文件,需要做特殊处理,例如:
find . -name "hello world.txt" -print0 | xargs -0 ls -lh$ find . -name "hello world.txt" -print0 | xargs -0 ls -lh -rw-rw-r-- 1 admin admin 0 Jul 2 14:34 ./hello world.txt $ find . -name "hello world.txt" -exec ls -lh {} \; -rw-rw-r-- 1 admin admin 0 Jul 2 14:34 ./hello world.txt
-