公众号:北野茶缸子
前言
如ls, echo 等等在内的命令,并不能直接接受多行文本。
比如:
代码语言:javascript复制❯ conda info -e | echo
Exception ignored in: <_io.TextIOWrapper name='<stdout>' mode='w' encoding='utf-8'>
BrokenPipeError: [Errno 32] Broken pipe
这时候我们就可以使用xargs 命令了。它的作用是将管道或标准输入的数据转换成小块分段传递给其他命令。
此外,因为有的命令并不能直接通过管道符号传递内容,比如ls
。简单来说,我们可以将多行的内容通过管道和xargs,将其传递给其他命令。这对于可以接受多个参数的命令来说,非常好用,我们就不需要在这些命令后,繁琐地一个个手写这些内容了。
一些使用场景
1-批量删除进程
有时候我们进行多进程操作时,可能会同时提交多个命令:
代码语言:javascript复制❯ sleep 10000 &
[1] 51241
❯ sleep 1000 &
[2] 51274
❯ sleep 100 &
[3] 51281
❯ ps -ef | grep sleep | grep -v grep
501 51241 37945 0 7:32下午 ttys000 0:00.01 sleep 10000
501 51274 37945 0 7:32下午 ttys000 0:00.00 sleep 1000
501 51281 37945 0 7:32下午 ttys000 0:00.01 sleep 100
通过ps
获取对应命令的静态信息,提取第二行的PID 再kill 即可:
❯ ps -ef | grep sleep | grep -v grep | awk '{print $2}' | xargs kill
2-打印查找到的文件
代码语言:javascript复制find . -ctime 20 | xargs ls -lh
3-删除文件或conda环境
代码语言:javascript复制conda info -e | sed '1,2d' | awk '{print $1}' | grep -v base | xargs -I {} conda env remove -y -p {}
我尝试清除了除base 以外的所有conda 环境。-I
参数可以指定一个符号,xargs 会将管道符号前获取的内容传递到后面对应符号的位置作为参数传入。
单独使用
参考:xargs 命令教程 - 阮一峰的网络日志[1]
我们也可以不使用管道符号,而通过标准输入传递给xargs,再通过xargs 传递给其他命令作为参数:
代码语言:javascript复制❯ xargs find -name
"*.txt"
./foo.txt
./hello.txt
一些参数
默认下,xargs 将换行符和空格作为分隔符,我们可以通过-d参数指定其他分隔符。
-p 参数则是,打印出将要执行的命令,相当于在命令执行前,先echo 出来,进行确认:
代码语言:javascript复制❯ ps -ef | grep sleep | grep -v grep | awk '{print $2}' | xargs -p kill
kill 59791 59799 59801?...
只有输入y 确认后,才会执行相关的命令:
代码语言:javascript复制❯ ps -ef | grep sleep | grep -v grep | awk '{print $2}' | xargs -p kill
kill 59791 59799 59801?...y
[3] 59801 terminated sleep 10000
[2] 59799 terminated sleep 10000
[1] 59791 terminated sleep 10000
-t 参数则是打印并执行。
-L 参数同时指定多行作为参数输入。-n 参数则指定多少项作为参数输入。同时考虑了多行为同一命令的参数,或一行包含了多个参数。
代码语言:javascript复制echo {0..9} | xargs -n 2 echo
0 1
2 3
4 5
6 7
8 9
参考资料
[1]
xargs 命令教程 - 阮一峰的网络日志: https://ruanyifeng.com/blog/2019/08/xargs-tutorial.html