bash中find的三个print参数区别,xargs命令使用要求

find -print|-print0|-printf 输出内容各不同,也在不同的场景中使用。

显示符合条件文件的权限,使用-exec ls -l {} \;效率不高。

sudo find /etc/letsencrypt -type f -name "*.pem" -exec ls -l {} \;

改用:

# 方式一:通过 xargs 执行 ls -l
sudo find /etc/letsencrypt -type f -name "*.pem"|xargs sudo ls -l

# 方式二:通过 -print 模拟 ls -l
sudo find /data/x -printf "%M %6u:%-6g %12s Bytes %Ty-%Tm-%Td %TH:%TM %p\n"
# 效果如下
-rw-r--r--   root:root        2461891 Bytes 26-01-15 01:00 /data/x/dump/260115_log.7z
drwxr-xr-x   root:root           4096 Bytes 26-01-16 00:00 /data/x/rpFiles
-rw-r--r--   root:root        2841642 Bytes 26-01-16 00:00 /data/x/rpFiles/liang.tar.gz
-rw-r--r--   root:root            203 Bytes 25-12-13 00:00 /data/x/rpFiles/rpFiles_Abnormal.log
drwxr-x---   root:adm            4096 Bytes 26-01-16 01:06 /data/x/b
-rw-r--r--   root:root         499474 Bytes 26-01-12 01:06 /data/x/b/260112_db.7z
-rw-r--r--    lat:ubuntu       521266 Bytes 26-01-10 01:06 /data/x/b/260110_db.7z
-rw-r--r--   root:root       26420430 Bytes 25-12-13 00:51 /data/x/b/251212_pngBak.7z
-rw-r--r--   root:root      134300643 Bytes 26-01-15 01:06 /data/x/b/260115_file.7z
-rw-r--r--   root:root         502434 Bytes 26-01-11 01:06 /data/x/b/260111_db.7z

-printf格式解说

  • %M符号权限 %u:%g所有者与组名 %s字节大小 %Ty-%Tm-%Td %TH:%TM到分钟的时间
  • %p完整路径=%h文件所在目录+’/’+%f文件名 %l符号链接目标 %Y文件类型
    • 如果路径或文件名中有空格,需要使用转义符:\"%p\",在输出时就是:"/data/x/b/260111_db.7z"
  • \t制表符 \n换行符,更多格式查看
  • 格式修饰符:没有左对齐默认是右对齐
    • 格式修饰符的通用语法:%[标志(控制对齐、填充等)][最小字段宽度][.精度(控制字符串截断或数字精度)]说明符,示例:%6u:%-6g %12s
    • -:指定为左对齐,否则为右对齐;
    • 6/12:最小字段宽度为6/12个字符,不足用空格填充,超过会扩展。%12s可以放下999G文件小的长度了。
    • %12s是使用空格填充,而%012s是使用0填充。
    • %-20.15f...是左对齐,最小宽度20,但文件名最多只显示前15位,超过使用...表示。更多请看man文档。

三个print参数区别

  • 需要自定义格式 → 用 -printf
  • 需要管道处理文件名 → 用 -print-print0,区别如下:
    • -print是一行一个列,多个文件会换行;多少个文件或目录,就输出多少行。
    • -print0是在一行里输入,多个文件之间使用不可见的 NULL 字符(\0 分隔。

-print0的作用:在处理包含特殊字符(如空格、换行符、制表符等)的文件名时特别有用,可以安全地处理任何文件名。示例:

find . -name "*.txt" -print
./my file.txt
./file with spaces.txt

当用 xargs处理时:

find . -name "*.txt" | xargs ls
# 会被误解为5个文件:my, file.txt, file, with, spaces.txt...

此时,需要-print0xargs -0组合使用:

find . -name "*.txt" -print0 | xargs -0 rm

以上还只是空格,还会存在含有换行符、制表符之类。另外,要注意不是所有命令都支持 NULL(\0)分隔符,而-print0只能与支持-0参数的命令配合使用。

黄金法则:当文件名来源不确定时,总是使用 -print0 | xargs -0 组合,这是处理文件名最安全的方式。

xargs

xargs 默认的命令是 echo,这意味着通过管道传递给 xargs 的输入将会包含换行和空白,不过通过 xargs 的处理,换行和空白将被空格取代。

xargs 是一个强有力的命令,它能够捕获一个命令的输出,然后传递给另外一个命令。xargs 一般是和管道一起使用,很多命令不支持管道比如ls -l

命令格式:somecommand |xargs -item command

参数:

  • -a file 从文件中读入作为 stdin
  • -e flag ,注意有的时候可能会是-E,flag必须是一个以空格分隔的标志,当xargs分析到含有flag这个标志的时候就停止。
  • -p 当每次执行一个argument的时候询问一次用户
  • -n num 后面加次数,表示命令在执行的时候一次用的argument的个数,默认是用所有的
  • -t 表示先打印命令,然后再执行
  • -i 或者是-I,这得看linux支持了,将xargs的每项名称,一般是一行一行赋值给 {},可以用 {} 代替。
  • -r no-run-if-empty 当xargs的输入为空的时候则停止xargs,不用再去执行了。
  • -s num 命令行的最大字符数,指的是 xargs 后面那个命令的最大命令行字符数。
  • -L num 从标准输入一次读取 num 行送给 command 命令。
  • -l 同 -L。
  • -d delim 分隔符,默认的xargs分隔符是回车,argument的分隔符是空格,这里修改的是xargs的分隔符。
  • -x exit的意思,主要是配合-s使用。。
  • -P 修改最大的进程数,默认是1,为0时候为as many as it can ,这个例子我没有想到,应该平时都用不到的吧。
  • -0 将 \0 作为定界符。

xargs 的使用示例1

带#为命令,无#为输出:

# cat test.txt
a b c d e f g
h i j k l m n
o p q
r s t
u v w x y z

# cat test.txt | xargs
a b c d e f g h i j k l m n o p q r s t u v w x y z

# cat test.txt | xargs -n3
a b c
d e f
g h i
j k l
m n o
p q r
s t u
v w x
y z

# echo "nameXnameXnameXname" | xargs -dX -n2
name name
name name

xargs 的使用示例2:对后面命令的要求

  • 命令要支持多文件输入,比如:lsrmmkdir;还可以指定,每次输入多少个文件。
  • 命令如果不支持多文件输入,只能使用 -I 逐个处理。

查找 /path/to/directory 目录下所有以 .txt 结尾的文件,并将它们的路径传递给 xargs 命令。

  • -I {} 选项告诉 xargs 命令将每个文件路径作为占位符传递给 mv 命令。
  • mv 命令将文件重命名为以 .md 结尾的文件。
find /path/to/directory -name "*.txt" | xargs -I {} mv {} {}.md

在文件多到直接使用rm -rf *会卡时,则使用 find + xargs 是绝配。

# -n 10是每次删除10个文件。
find ./ -type f | xargs -n 10 rm -f

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注