how to use linux xargs command


Guide

param input && stdin

linux命令可以从两个地方读取要处理的内容

  • 通过命令行参数输入,通过main函数的argc,argv获取
  • 标准输入stdin,通过scanf或者cin获取

然后产生输出

  • 标准输出stdout,通过printf或者cout输出

命令类型

  • 部分命令可以接受参数输入+标准输入stdin,比如cat、grep等。
  • 部分命令只接受参数输入,不接受标准输入stdin,比如kill、rm等。
int main(int argc, char*argv[])
{
    // argc, argv
    // cin, scanf 
    // cout printf
    return 0;
}

指定参数输入,则从参数输入读取内容;
未指定或者在命令的最后使用 -则从标准输入读取内容;
管道将stdout重定向到后续命令的stdin;

cat/grep

cat

  • 指定参数输入1.txt,文件存在【从参数输入读取】

    cat 1.txt
    hello world 
    
  • 指定参数输入1.txt,文件不存在【从参数输入读取】

    cat 1.txt2
    cat: 1.txt2: No such file or directory
    
  • 未指定参数输入【从stdin读取】

    cat
    hello
    hello
    ^C
    
  • 使用-【从stdin读取】

    cat -
    hello
    hello
    ^C
    
  • 指定参数输入1.txt,文件存在+使用-【从参数输入读取+stdin读取】

    cat 1.txt -
    hello world 
    hello
    hello
    ^C
    

cat + pipe

  • 指定参数输入1.txt,文件存在 + stdin【only从参数输入读取】

    echo 'hello' | cat 1.txt
    hello world 
    
  • 指定参数输入1.txt,文件不存在【only从参数输入读取】

    echo 'hello' | cat 1.txt2
    cat: 1.txt2: No such file or directory
    
  • 未指定参数输入【从stdin读取】

    echo 'hello' | cat
    hello
    
  • 使用-【从stdin读取】

    echo 'hello' | cat -
    hello
    
  • 指定参数输入1.txt,文件存在+使用-【从参数输入读取+stdin读取】

    echo 'hello' | cat 1.txt -
    hello world 
    hello
    

grep + pipe

  • 指定参数输入1.txt,文件存在 + stdin【only从参数输入读取】

    echo 'hello' | grep 'hello' 1.txt
    hello world 
    
  • 指定参数输入1.txt,文件存在+使用-【从参数输入读取+stdin读取】

    echo 'hello' | grep 'hello' 1.txt -
    1.txt:hello world
    (standard input):hello
    

kill/rm

  • kill不接受stdin

    echo '516' | kill
    kill: usage: kill [-s sigspec | -n signum | -sigspec] pid | jobspec ... or kill -l [sigspec]
    
  • rm 不接受stdin

      echo 'test' | rm -f
    

xargs

如何实现echo '516' | kill类似的效果?

  • method 1

      kill `ps -ef | grep 'xxx'`  # same as   kill $pid
    
  • method 2

      for pid in $(ps -aux | grep "some search" | awk '{print $2}');                 do kill -9 $pid; 
      done 
    
  • method 3

      ps -ef | grep 'xxx' | xargs kill  
    

xargs命令可以通过管道接受字符串,并将接收到的字符串通过空格分割成许多参数(默认情况下是通过空格分割) 然后将参数传递给其后面的命令,作为后面命令的命令行参数输入

xargs可以实现命令的参数输入

xargs vs pipe

  • pipe 使得–help成为cat的stdin

    $ echo '--help' | cat 
    --help
    
  • xargs使得–help成为cat的命令行参数输入,等价于 cat --help

    $ echo '--help' | xargs cat 
    Usage: cat [OPTION]... [FILE]...
    Concatenate FILE(s) to standard output.
    
    With no FILE, or when FILE is -, read standard input.
    
      -A, --show-all           equivalent to -vET
      -b, --number-nonblank    number nonempty output lines, overrides -n
      -e                       equivalent to -vE
      -E, --show-ends          display $ at end of each line
      -n, --number             number all output lines
      -s, --squeeze-blank      suppress repeated empty output lines
      -t                       equivalent to -vT
      -T, --show-tabs          display TAB characters as ^I
      -u                       (ignored)
      -v, --show-nonprinting   use ^ and M- notation, except for LFD and TAB
          --help     display this help and exit
          --version  output version information and exit
    
    Examples:
      cat f - g  Output f's contents, then standard input, then g's contents.
      cat        Copy standard input to standard output.
    
    GNU coreutils online help: <http://www.gnu.org/software/coreutils/>
    Full documentation at: <http://www.gnu.org/software/coreutils/cat>
    or available locally via: info '(coreutils) cat invocation'
    

echo '1.txt 2.txt' | xargs cat 等价于 cat 1.txt 2.txt

xargs options

-d 选项

默认情况下xargs将其标准输入中的内容以空白(包括空格、Tab、回车换行等)分割成多个之后当作命令行参数传递给其后面的命令,并运行之,我们可以使用 -d 命令指定分隔符

  echo '[email protected]@33' | xargs echo 
  [email protected]@33

  echo '[email protected]@33' | xargs -d '@' echo 
  11 22 33

等价于

echo 11 22 33

-p 选项

使用该选项之后xargs并不会马上执行其后面的命令,而是输出即将要执行的完整的命令(包括命令以及传递给命令的命令行参数),询问是否执行,输入 y 才继续执行,否则不执行。这种方式可以清楚的看到执行的命令是什么样子,也就是xargs传递给命令的参数是什么

  echo '[email protected]@33' | xargs -p -d '@'  echo 
  echo 11 22 33
   ?...yes
  11 22 33

-n 选项

该选项表示将xargs生成的命令行参数,每次传递几个参数给其后面的命令执行,例如如果xargs从标准输入中读入内容,然后以分隔符分割之后生成的命令行参数有10个,使用 -n 3 之后表示一次传递给xargs后面的命令是3个参数,因为一共有10个参数,所以要执行4次,才能将参数用完。

  echo '[email protected]@[email protected]@[email protected]@[email protected]@[email protected]' | xargs -d '@' -n 3 echo 
  11 22 33
  44 55 66
  77 88 99
  00

等价于

echo 11 22 33
echo 44 55 66
echo 77 88 99
echo 00

使用-n 1得到类似于对循环处理的结果。

默认一次送入n个参数,一次处理完毕

ls *.txt | xargs -p cat 
cat 1.txt 2.txt 3.txt ?...y
111
222
333


等价与
cat 1.txt 2.txt 3.txt
111
222
333

-n 1一次送入1个参数,相当于循环处理了3次,每次处理一个文件

ls *.txt | xargs -n 1 -p cat 
cat 1.txt ?...y
111
cat 2.txt ?...y
222
cat 3.txt ?...y
333



等价与
cat 1.txt
111

cat 2.txt
222

cat 3.txt
333

-E 选项

有的系统的xargs版本可能是-e eof-str,该选项指定一个字符串,当xargs解析出多个命令行参数的时候,如果搜索到-e指定的命令行参数,则只会将-e指定的命令行参数之前的参数(不包括-e指定的这个参数)传递给xargs后面的命令

echo '11 22 33 44' | xargs -E '33' echo 
11 22 

-E只有在xargs不指定-d或者-0的时候有效
-0 选项表示以 ‘\0’ 为分隔符,一般与find结合使用
-0 等同于 -d ‘\0’

使用-d

  echo '[email protected]@[email protected]@[email protected]@[email protected]@[email protected] aa 33 bb' | xargs -E '33' -d '@' -p  echo
  xargs: warning: the -E option has no effect if -0 or -d is used.

  echo 11 22 33 44 55 66 77 88 99 00 aa 33 bb
   ?...y
  11 22 33 44 55 66 77 88 99 00 aa 33 bb

不使用-d

  echo '[email protected]@[email protected]@[email protected]@[email protected]@[email protected] aa 33 bb' | xargs -E '33' -p  echo
  echo [email protected]@[email protected]@[email protected]@[email protected]@[email protected] aa ?...y
  [email protected]@[email protected]@[email protected]@[email protected]@[email protected] aa

-0 && find

find . -name "*.txt"
./2.txt
./3.txt
./1.txt     => 默认情况下find的输出结果是每条记录后面加上换行,也就是每条记录是一个新行

find . -name "*.txt" -print0
./2.txt./3.txt./1.txt     => 加上 -print0 参数表示find输出的每条结果后面加上 '\0' 而不是换行

find . -name "*.txt" -print0 | xargs -0 echo 
./2.txt ./3.txt ./1.txt

等同于
find . -name "*.txt" -print0 | xargs -d '\0' echo 
./2.txt ./3.txt ./1.txt

默认使用空白分隔符(换行符也是)
find . -name "*.txt"  | xargs  echo 
./2.txt ./3.txt ./1.txt

xargs as loop

one image at once

python text_recognition.py  --east frozen_east_text_detection.pb --image 1.jpg

for loop

find roi/ -name "*.jpg" | xargs -n 1 python text_recognition.py  --east frozen_east_text_detection.pb --image 

ls roi/*.jpg | xargs -n 1 python text_recognition.py  --east frozen_east_text_detection.pb --image 

Reference

History

  • 20180920: created.

Author: kezunlin
Reprint policy: All articles in this blog are used except for special statements CC BY 4.0 reprint polocy. If reproduced, please indicate source kezunlin !
评论
  TOC