驾驭unix find 输出的n种方式
find 命令是 Linux/Unix 系统管理员和开发者工具箱中的瑞士军刀,它能帮助我们根据各种条件定位文件.一旦找到了这些文件,我们通常需要对它们执行某些操作——删除、复制、修改权限,或者更复杂的操作.之前我一直使用 xargs 来将 find 的输出作为参数传递给其他命令,但是今天发现xargs处理复杂操作的时候有点麻烦,就尝试了其他方法.
xargs
xargs [options] [command [initial-arguments]]
本质上是替换从标准输入读取数据(用空格或者换行分割),然后将这些数据作为参数传递给另一个命令来执行(默认是echo
)
xargs 通过将大量输入参数“打包”分批传递给目标命令,从而显著减少目标命令的调用次数.这样做避免了为每个输入项都启动一个新进程的巨大开销,因此极大地提高了处理大量输入的性能.此外,它还提供了如 -n, -L
选项来控制打包方式,以及 -P 选项来支持并行处理,进一步优化效率.
由于unix文件名可能带有空格或者换行,所以-0
option,并给unix程序(如find
)传递-print0
来用空字符作为分割符,因为unix哲学的(让每个程序都成为一个过滤器 (Make every program a filter))
例子
1 |
|
更复杂的例子(openwrt)更新所有软件包
1 |
|
实现细节
什么叫做”The command line for command is built up until it reaches a system-defined limit”
对于:
1 |
|
可以用strace
看看他调用了多少次echo
1 |
|
多线程处理
可以用 -P
来控制线程数量
1 |
|
如果想传递全局变量进去:
1 |
|
find
自带的exec
删除所有找到的 .log 文件 (每个文件执行一次 rm)
1 |
|
高效删除所有找到的 .log 文件(类似与xargs)
1 |
|
还有execdir(在目录下执行)
while read
循环
1 |
|
-print0
:find
使用 null 字符 (\0
) 作为文件名分隔符.IFS=
:清空内部字段分隔符,防止read
意外处理文件名前后的空白.read -r
: 禁止反斜杠转义.read -d $'\0'
:read
以 null 字符作为记录分隔符.
可读性高(复杂操作不用像xargs全部写近''
里面(没语法高亮QAQ))但是这样的性能不如xargs
选择?
- 对于大多数标准的批量文件操作,
find ... -exec command {} +
是首选,因为它兼具效率、安全性和简洁性. - 如果需要在 shell 脚本中对每个文件执行更复杂的逻辑,
find ... -print0 | while IFS= read -r -d $'\0' file; do ... done
是最安全和最灵活的选择. - 当你确实需要 xargs 提供的特定功能(如并行处理 -P)时,确保使用
find -print0 | xargs -0 ...
来保证文件名处理的安全性.