分享

Linux 中xargs 用法

 捉虫子吃的松树 2012-12-19
xargs [ -p ] [ -t ] [ -e [ EOFString ] ] [ -E EOFString ] [ -i [
   ReplaceString ] ] [ -I ReplaceString ] [ -l [ Number ] ] [ -L Number ] [ -n
   Number [ -x ] ] [ -s Size ] [ Command [ Argument ... ] ]
   注: 不要在小写的符号和参数之间加空格。
 
xargs 可以读入 stdin 的资料,并且以空白字符或换行符作分隔,将 stdin 的资料分隔成为 arguments 。因为是以空白字符作为分隔,所以,如果有一些文件名或者是其他意义的名词内含有空白字符的时候, xargs 可能会误判。!
 参数∶
 -0 ∶如果输入的 stdin 含有特殊字符,例如 `, \, 空白键等等字元时,这个 -0 参数可以将他还原成一般字元。这个参数可以用于特殊状态喔!
 -e ∶这个是 EOF (end of file) 的意思。后面可以接一个字串,当 xargs 分析到这个字串时,就会停止继续工作!
 -p ∶在执行每个指令的 argument 时,都会询问使用者的意思;
 -n ∶后面接次数,每次 command 指令执行时,要使用几个参数的意思。看范例三。
 当 xargs 后面没有接任何的指令时,预设是以 echo 来进行输出喔!
 范例∶
 范例一∶将 /etc/passwd 内的第一栏取出,仅取三行,使用 finger 这个指令将每个账号内容秀出来
 [root@linux ~]# cut -d':' -f1 < /etc/passwd |head -n 3| xargs finger
 Login: root Name: root
 Directory: /root Shell: /bin/bash
 Never logged in.
 No mail.
 No Plan.
 ......底下省略.....
 # 由 finger account 可以取得该账号的相关说明内容,例如上面的输出就是 finger root后的结果。在这个例子当中,我们利用 cut 取出账号名称,用 head 取出三个账号,最后则是由 xargs 将三个账号的名称变成 finger 后面需要的参数!
 范例二∶同上,但是每次执行 finger 时,都要询问使用者是否动作?
 [root@linux ~]# cut -d':' -f1 < /etc/passwd |head -n 3| xargs -p finger
 finger root bin daemon ?...y
 ......底下省略.....
 # 呵呵!这个 -p 的参数有趣了吧?!他可以让使用者的使用过程中,被询问到每个指令是否执行!
 范例三∶将所有的 /etc/passwd 内的账号都以 finger 查阅,但一次仅查阅五个账号
 [root@linux ~]# cut -d':' -f1 < /etc/passwd | xargs -p -n 5 finger
 finger root bin daemon adm lp ?...y
 ......底下省略.....
 # 在这里鸟哥使用了 -p 这个参数来让您对于 -n 更有概念。一般来说,某些指令后面可以接的 arguments 是有限制的,不能无限制的累加,此时,我们可以利用 -n来帮助我们将参数分成数个部分,每个部分分别再以指令来执行!这样就 OK 啦!^_^
 [root@linux ~]#
 范例四∶同上,但是当分析到 lp 就结束这串指令?
 [root@linux ~]# cut -d':' -f1 < /etc/passwd | xargs -p -e'lp' finger
 finger root bin daemon adm ?...
 # 仔细与上面的案例做比较。也同时注意,那个 -e'lp' 是连在一起的,中间没有空白键。
 # 上个例子当中,第五个参数是 lp 啊,那么我们下达 -e'lp' 后,则分析到 lp这个字串时,后面的其他 stdin 的内容就会被 xargs 舍弃掉了!
 find . -name '*.py' | xargs wc -l
 递归查找所有Emacs备份文件并删除:
 find . -name '*~' | xargs rm
 递归查找所有Python文件并搜索import语句:
 find . -name '*.py' | xargs grep 'import'
 处理文件/目录名中的空格
 上面的例子有一个问题,如果文件或是目录名含有空格,则可能会有些问题,这是因为xargs默认会按照空白字符来划分输入。一个简单的解决办法就是告诉find使用NUL(\0)来分割结果(通过向find提供-print0选项),并且告诉xargs也使用Nul来分隔输入(-0)。
 删除备份文件,即使含有空格:
 find . -name '*~' -print0 | xargs -0 rm
 参数位置
 上面的例子中xargs从标准输入读取所有非空的元素并将他们连接起来提供给给定的命令进行执行,这在很多情况下会非常有用,尽管如此,有时你可能想要在命令中间插入一个参数,此时-J标记就排上用场了,xargs会为-J参数后面的字符串加上输入然后再执行。
 将所有备份文件复制到backups目录下:
 find . -name '*~' -print 0 | xargs -0 -J % cp % ~/backups
 最大命令长度
 有时通过管道传递给xargs的输入可能会造成要执行的命令超出最大命令行长度限制,你可以通过下面的命令得到命令行的最大长度:
 getconf ARG_MAX
 为了避免越限,xargs对于结果命令有它自己的最大长度限制,如果提供的参数有可能会造成调用的命令超出长度限制,则xargs会将输入分割成多个部分,并多次调用目标命令,默认的长度限制是4096,这可能要远远小于大多数现在系统的ARG_MAX设置,你可以通过向xargs提供-s标识来覆盖这个默认设置,当你对一个很大的源代码仓库进行操作时,这会显得尤其有用。
 指定参数数量
 如果你要执行的命令只接受1个或是2个参数,比如使用diff命令来对2个文件进行比较,那么xargs的-n选项就会非常有用,它可以指定一次向目标命令提供几个参数,如果参数数量多于你制定的数量,则命令将会被重复调用,直到所有输入都已经得到执行。注意,最后一次调用的参数有可能会少于指定的参数数量,下面让我们来看一个简单的例子:
 $ echo {0..9} | xargs -n 2
 0 1
 2 3
 4 5
 6 7
 8 9
 同样的,你也可以使用-L参数制定每次只对某几行的输入进行操作,比如-L 1将每次从输入中取一行作为参数传递给待执行的命令,当然,你可以将1改为任意行,但1是最常用的,下面这条命令将演示如何得到每个git commit的代码变化:
 git log --format="%H %P" | xargs -L 1 git diff
 并行执行命令
 你或许会使用xargs调用某些需要密集计算的命令,如果xargs可以利用你电脑上的多核计算能力,那该有多美妙?没错,-P参数就是干这个的,通过这个参数xargs可以一次并行的调用多个命令,举个例子,你可以通过它来并行的运行多个ffmpeg编码器,不过,还是让我们来个更简单一点的例子吧:
 并行休眠
 $ time echo {1..5} | xargs -n 1 -P 5 sleep
 real 0m5.013s
 user 0m0.003s
 sys 0m0.014s
 线性休眠
 $ time echo {1..5} | xargs -n 1 sleep
 real 0m15.022s
 user 0m0.004s
 sys 0m0.015s
 如果你对使用xargs进行并行计算感兴趣,那么你或许应该看看GNU parallel,相比较而言,xargs的优势就是大多数系统默认都支持它,并且在BSD和OS X上也可以很容易的安装,但是parallel则有许多非常赞的特性。
 仅对上文FIND用法进行补充.完全看不懂,只有最下面一句能用得到:
 
 xargs
 大多数 Linux 命令都会产生输出:文件列表、字符串列表等。但如果要使用其他某个命令并将前一个命令的输出作为参数该怎么办?例如,file 命令显示文件类型(可执行文件、ascii 文本等);您可以处理输出,使其仅显示文件名,现在您希望将这些名称传递给 ls -l 命令以查看时间戳记。xargs 命令就是用来完成此项工作的。它允许您对输出执行其他某些命令。
 
 xargs – build and execute command lines from standard input
 
 在使用find命令的-exec选项处理匹配到的文件时, find命令将所有匹配到的文件一起传递给exec执行。但有些系统对能够传递给exec的命令长度有限制,这样在find命令运行几分钟之后,就会出现溢出错误。错误信息通常是“参数列太长”或“参数列溢出”。这就是xargs命令的用处所在,特别是与find命令一起使用。
 
 
 记住下面这个来自于第 1 部分中的语法:
 
 file -Lz * | grep ASCII | cut -d":” -f1 | xargs ls -ltr
 
 让我们来剖析这个命令字符串。第一个,file -Lz *,用于查找是符号链接或者经过压缩的文件。它将输出传递给下一个命令 grep ASCII,该命令在其中搜索 “ASCII” 字符串并产生如下所示的输出:
 alert_DBA102.log: ASCII English text
 alert_DBA102.log.Z: ASCII text (compress’d data 16 bits)
 dba102_asmb_12307.trc.Z: ASCII English text (compress’d data 16 bits)
 dba102_asmb_20653.trc.Z: ASCII English text (compress’d data 16 bits)
 
 由于我们只对文件名感兴趣,因此我们应用下一个命令 cut -d”:” -f1,仅显示第一个字段:
 alert_DBA102.log
 alert_DBA102.log.Z
 dba102_asmb_12307.trc.Z
 dba102_asmb_20653.trc.Z
 
 现在,我们希望使用 ls -l 命令,将上述列表作为参数进行传递,一次传递一个。xargs 命令允许您这样做。最后一部分,xargs ls -ltr,用于接收输出并对其执行 ls -ltr 命令,如下所示:
 
 ls -ltr alert_DBA102.log
 ls -ltr alert_DBA102.log.Z
 ls -ltr dba102_asmb_12307.trc.Z
 ls -ltr dba102_asmb_20653.trc.Z
 
 因此,xargs 本身虽然没有多大用处,但在与其他命令相结合时,它的功能非常强大。
 
 下面是另一个示例,我们希望计算这些文件中的行数:
 
 $ file * | grep ASCII | cut -d”:” -f1 | xargs wc -l
 47853 alert_DBA102.log
 19 dba102_cjq0_14493.trc
 29053 dba102_mmnl_14497.trc
 154 dba102_reco_14491.trc
 43 dba102_rvwr_14518.trc
 77122 total
 
 (注:上述任务还可用以下命令完成:)
 
 $ wc -l ‘file * | grep ASCII | cut -d”:” -f1 | grep ASCII | cut -d”:” -f1‘
 
 该 xargs 版本用于阐释概念。Linux 可以用几种方法来完成同一个任务;请使用最适合您的情况的方法。
 
 使用该方法,您可以快速重命名目录中的文件。
 
 $ ls | xargs -t -i mv {} {}.bak
 
 -i 选项告诉 xargs 用每项的名称替换 {}。-t 选项指示 xargs 先打印命令,然后再执行。
 
 另一个非常有用的操作是当您使用 vi 打开要编辑的文件时:
 
 $ file * | grep ASCII | cut -d”:” -f1 | xargs vi
 
 该命令使用 vi 逐个打开文件。当您希望搜索多个文件并打开它们进行编辑时,使用该命令非常方便。
 
 它还有几个选项。最有用的可能是 -p 选项,它使操作具有可交互性:
 
 $ file * | grep ASCII | cut -d”:” -f1 | xargs -p vi
 vi alert_DBA102.log dba102_cjq0_14493.trc dba102_mmnl_14497.trc dba102_reco_14491.trc dba102_rvwr_14518.trc ?…
 
 此处的 xarg 要求您在运行每个命令之前进行确认。如果您按下 “y”,则执行命令。当您对文件进行某些可能有破坏且不可恢复的操作(如删除或覆盖)时,您会发现该选项非常有用。
 
 -t 选项使用一个详细模式;它显示要运行的命令,是调试过程中一个非常有帮助的选项。
 
 如果传递给 xargs 的输出为空怎么办?考虑以下命令:
 
 $ file * | grep SSSSSS | cut -d”:” -f1 | xargs -t wc -l
 wc -l
 0
 $
 
 在此处,搜索 “SSSSSS” 后没有匹配的内容;因此 xargs 的输入均为空,如第二行所示(由于我们使用 -t 这个详细选项而产生的结果)。虽然这可能会有所帮助,但在某些情况下,如果没有要处理的内容,您可能希望停止 xargs;如果是这样,可以使用 -r 选项:
 $ file * | grep SSSSSS | cut -d”:” -f1 | xargs -t -r wc -l
 $
 
 如果没有要运行的内容,该命令退出。
 
 假设您希望使用 rm 命令(该命令将作为 xargs 命令的参数)删除文件。然而,rm 只能接受有限数量的参数。如果您的参数列表超出该限制怎么办?xargs 的 -n 选项限制单个命令行的参数个数。
 
 下面显示了如何限制每个命令行仅使用两个参数:即使向 xargs ls -ltr 传递五个文件,但每次向 ls -ltr 仅传递两个文件。
 
 $ file * | grep ASCII | cut -d”:” -f1 | xargs -t -n2 ls -ltr
 ls -ltr alert_DBA102.log dba102_cjq0_14493.trc
 -rw-r—– 1 oracle dba 738 Aug 10 19:18 dba102_cjq0_14493.trc
 -rw-r–r– 1 oracle dba 2410225 Aug 13 05:31 alert_DBA102.log
 ls -ltr dba102_mmnl_14497.trc dba102_reco_14491.trc
 -rw-r—– 1 oracle dba 5386163 Aug 10 17:55 dba102_mmnl_14497.trc
 -rw-r—– 1 oracle dba 6808 Aug 13 05:21 dba102_reco_14491.trc
 ls -ltr dba102_rvwr_14518.trc
 -rw-r—– 1 oracle dba 2087 Aug 10 04:30 dba102_rvwr_14518.trc
 
 使用该方法,您可以快速重命名目录中的文件。
 
 $ ls | xargs -t -i mv {} {}.bak
 
 -i 选项告诉 xargs 用每项的名称替换 {}。
 
 我需要将一个用.svn管理的项目改成由CVS来管理,因此,在导入整个项目到CVS中之前,我需要删除所有目录下以及子孙目录下的.svn目录及.svn目录下的的子目录和文件。我一直寻找一种最简单的方法,最后写了一个程序去干这事情。结果同事告诉我只需要一条指令就可以了:find -name ‘.svn’ |xargs rm -rf
 这个教训非常惨重,我一生讨厌傻瓜,可那一刻发现自己是最大的傻瓜!
 
 是的,虽然我们——至少是我,天天使用LINUX但是真的是在高效的使用这个系统吗?不,很多时候并没有花时间去研究它,使用一些固有愚蠢的方式和思维模式在使用这个系统。
 
 1. 建立多级目录:
 
 mkidr 指令用来建立目录,事实上,我们一直都是这么干的。但是在这么使用的时候我们并没有去看它的那些参数提供了哪些额外的功能.
 
 mkidr -p /share/dragon ; 在根目录下建立share目录,并在/share目录下建立dragon目录。mkdir -p guicmd/{bin,lib,src,share/version,doc/{html,pdf,info,man}}
 ;用来建立一个复杂的项目目录树。
 
 2.find 配合xargs使用:
 
 find -name ‘.svn’ |xargs rm -rf ;这个不用说了,就是我前面提到的。
 xargs更加象一个筛选器,将符合管道传递过来的文件名的内容一并处理掉,这是一个极度高效的方法。
 
 三、xargs
 
 xargs – build and execute command lines from standard input
 
 在使用find命令的-exec选项处理匹配到的文件时, find命令将所有匹配到的文件一起传递给exec执行。但有些系统对能够传递给exec的命令长度有限制,这样在find命令运行几分钟之后,就会出现溢出错误。错误信息通常是“参数列太长”或“参数列溢出”。这就是xargs命令的用处所在,特别是与find命令一起使用。
 
 find命令把匹配到的文件传递给xargs命令,而xargs命令每次只获取一部分文件而不是全部,不像-exec选项那样。这样它可以先处理最先获取的一部分文件,然后是下一批,并如此继续下去。
 
 在有些系统中,使用-exec选项会为处理每一个匹配到的文件而发起一个相应的进程,并非将匹配到的文件全部作为参数一次执行;这样在有些情况下就会出现进程过多,系统性能下降的问题,因而效率不高;
 
 而使用xargs命令则只有一个进程。另外,在使用xargs命令时,究竟是一次获取所有的参数,还是分批取得参数,以及每一次获取参数的数目都会根据该命令的选项及系统内核中相应的可调参数来确定。
 
 来看看xargs命令是如何同find命令一起使用的,并给出一些例子。
 
 下面的例子查找系统中的每一个普通文件,然后使用xargs命令来测试它们分别属于哪类文件
 
  
 
 #find . -type f -print | xargs file
 ./.kde/Autostart/Autorun.desktop: UTF-8 Unicode English text
 ./.kde/Autostart/.directory:      ISO-8859 text\
 ......
  
 
 在整个系统中查找内存信息转储文件(core dump) ,然后把结果保存到/tmp/core.log 文件中:
 
 $ find / -name "core" -print | xargs echo "" >/tmp/core.log
 上面这个执行太慢,我改成在当前目录下查找
 
 #find . -name "file*" -print | xargs echo "" > /temp/core.log
 # cat /temp/core.log
 ./file6
 
 在当前目录下查找所有用户具有读、写和执行权限的文件,并收回相应的写权限:
 
 <code># ls -l
 drwxrwxrwx    2 sam      adm          4096 10月 30 20:14 file6
 -rwxrwxrwx    2 sam      adm             0 10月 31 01:01 http3.conf
 -rwxrwxrwx    2 sam      adm             0 10月 31 01:01 httpd.conf
 # find . -perm -7 -print | xargs chmod o-w
 # ls -l
 drwxrwxr-x    2 sam      adm          4096 10月 30 20:14 file6
 -rwxrwxr-x    2 sam      adm             0 10月 31 01:01 http3.conf
 -rwxrwxr-x    2 sam      adm             0 10月 31 01:01 httpd.conf
 
  
 
 用grep命令在所有的普通文件中搜索hostname这个词:
 
  
 
 # find . -type f -print | xargs grep "hostname"
 ./httpd1.conf:#     different IP addresses or hostnames and have them handled by the
 ./httpd1.conf:# VirtualHost: If you want to maintain multiple domains/hostnames
 on your
 
 用grep命令在当前目录下的所有普通文件中搜索hostnames这个词:
 
 # find . -name \* -type f -print | xargs grep "hostnames"
 ./httpd1.conf:#     different IP addresses or hostnames and have them handled by the
 ./httpd1.conf:# VirtualHost: If you want to maintain multiple domains/hostnames
 on your
  
 
 注意,在上面的例子中, \用来取消find命令中的*在shell中的特殊含义。
 
 find命令配合使用exec和xargs可以使用户对所匹配到的文件执行几乎所有的命令。
 
 ============================================================
 
 打包操作系统里,所有.sh文件到abc.tar。
 
 1、操作系统里所有.sh文件,find的时候目录设定为"/",不要用"./"。
 2、打包整个操作系统的.sh文件,一次性打包可能会因为文件过多发生覆盖,建议设置xargs的-n,tar时进行追加。
 
 find / -name "*.sh" | xargs -n 100 tar -rvf abc.tar
 
 This entry was posted in LINUX and tagged find, linux, xargs by admin. Bookmark the permalink.
 ONE THOUGHT ON “LINUX中XARGS的用法”
 xargs是给命令传递参数的一个过滤器,也是组合多个命令的一个工具。它把一个数据流分割为一些足够小的块,以方便过滤器和命令进行处理。通常情况下,xargs从管道或者stdin中读取数据,但是它也能够从文件的输出中读取数据。xargs的默认命令是echo,这意味着通过管道传递给xargs的输入将会包含换行和空白,不过通过xargs的处理,换行和空白将被空格取代。
 
 xargs 是一个强有力的命令,它能够捕获一个命令的输出,然后传递给另外一个命令,下面是一些如何有效使用xargs 的实用例子。
 
 1. 当你尝试用rm 删除太多的文件,你可能得到一个错误信息:/bin/rm Argument list too long. 用xargs 去避免这个问题
 
 find ~ -name ‘*.log’ -print0 | xargs -0 rm -f
 
 
 
 2. 获得/etc/ 下所有*.conf 结尾的文件列表,有几种不同的方法能得到相同的结果,下面的例子仅仅是示范怎么实用xargs ,在这个例子中实用 xargs将find 命令的输出传递给ls -l
 
 # find /etc -name "*.conf" | xargs ls –l
 
 
 3. 假如你有一个文件包含了很多你希望下载的URL, 你能够使用xargs 下载所有链接
 
 # cat url-list.txt | xargs wget –c
 
 
 
 4. 查找所有的jpg 文件,并且压缩它
 
 # find / -name *.jpg -type f -print | xargs tar -cvzf images.tar.gz
 
 
 5. 拷贝所有的图片文件到一个外部的硬盘驱动 
 
 # ls *.jpg | xargs -n1 -i cp {} /external-hard-drive/directory
 
 
 
 EXAMPLES
 find /tmp -name core -type f -print | xargs /bin/rm -f
 Find files named core in or below the directory /tmp and delete them.  Note that this will work incorrectly if there are any filenames containing newlines or spaces.
 
 find /tmp -name core -type f -print0 | xargs -0 /bin/rm -f
 Find  files  named core in or below the directory /tmp and delete them, processing filenames in such a way that file or directory names containing spaces or newlines are correctly handled.
 
 find /tmp -depth -name core -type f -delete
 Find files named core in or below the directory /tmp and delete them, but more efficiently than in the previous example (because we avoid the need to use fork(2) and exec(2) to launch rm and we don't need the extra xargs process).
 
 cut -d: -f1 < /etc/passwd | sort | xargs echo
 Generates a compact listing of all the users on the system.
 
 xargs sh -c 'emacs "$@" < /dev/tty' emacs
 Launches the minimum number of copies of Emacs needed, one after the other, to edit the files listed on xargs' standard input.  This example achieves the same effect as BSD's -o option, but in a more flexible and portable way.

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多