我们可以利用管道将一个命令的stdout(标准输出)重定向到另一个命令的stdin(标准输入)。有些命令只能以命令行参数的形式接受数据,而无法通过stdin接受数据流。这时候就没法使用管道。那么xargs擅长将标准输入数据转换成命令行参数。xargs能够处理stdin并将其转换为特定命令的命令行参数。它也可以将单行或多行文本输入转换成其他格式。

1、xargs命令应该紧跟在管道操作符之后,以标准输入作为主要的源数据流。如command | xargs

2、xargs命令把从stdin接受到 的数据重新格式化,再将其作为参数提供给其他命令。xargs其作用类似于find命令中的exec。

a、将多行输入转换成单行输出。只需要将换行符移除,再用“ ”(空格)进行代替,就可以实现多行输入的转换。'\n'被解释成一个换行符,它其实就是多行文本之间的定界符。

eg:$cat example.txt

1 2 3 4 5 6

7 8 9 10

11 12

$ cat example.txt | xargs

1 2 3 4 5 6 7 8 9 10 11 12

b、将单行输入转换成多行输出。

指定每行最大的参数数量n,可以将任何来自stdin的文本划分成多行,每行n个参数。每个参数都是由“ ”(空格)隔开的字符串。空格是默认的定界符。

eg:$cat example.txt | xargs -n 3

1 2 3

4 5 6

7 8 9

10 11 12

3、工作原理

a、可以用自己的定界符来分隔参数。用-d选项为输入指定一个定制的定界符。

eg:$echo "splitXsplitXsplitXsplit" | xargs - d X

split split split split

b、结合-n选项,可以将输入划分成多行,而每行包含两个参数:

eg:$echo "splitXsplitXsplitXsplit" | xargs - d X -n 2

split split

split split

4、补充内容

1)、读取stdin,将格式化参数传递给命令

先编写一个小型的定制版echo来更好地理解用xargs提供命令行参数的方法:

#!/bin/bash

#文件名:cecho.sh

echo $* '#'

当参数传递给文件cecho.sh后,它会将这些参数打印出来,并以#字符作为结尾。如

$ ./cecho.sh arg1 arg2

arg1 arg2 #

a、有一个名为args.txt的参数列表文件,如下

$ cat args.txt

arg1

arg2

arg3

可以将这个命令执行多次,每次使用一个参数:

$ cat args.txt | xargs -n 1 ./cecho.sh

arg1 #

arg2 #

arg3 #

每次执行需要X个参数的命令时,使用:

INPUT | xargs -n X

如:

$ cat args.txt | xargs -n 2 ./cecho.sh

arg1 arg2 #

arg3 #

为了在执行命令时一次性提供所有的参数,可以使用:

$cat args.txt | xargs ./ cecho.sh

arg1 arg2 arg3 #

上面例子中,直接为特定的命令(cecho.sh)提供命令行参数。这些参数都源于args.txt文件。但实际上除了以上之外,还需要一些固定不变的命令参数。如

./cecho.sh -p arg1 -1

其中arg1是唯一的可变内容,其余部分都保持不变。我们可以从文件(args.txt)中读取参数,并按照下面的方式提供给命令:

./cecho.sh -p arg1 -1

./cecho.sh -p arg2 -1

./cecho.sh -p arg3 -1

xargs有一个-I选项,可以提供上面这种形式的命令执行序列。可以使用-I指定替换字符串,这个字符串在xarg扩展时会被替换掉。如果将-I与xargs结合使用,对于每一个参数,命令都会被执行一次。如

$cat args.txt | xargs -I {} ./cecho.sh -p {} -1

-p arg1 -1 #

-p arg2 -1 #

-p arg3 -1 #

-I {}指定了字符串。对于每一个命令参数,字符串{}都会被从stdin读取到的参数替换掉。

注意:使用-I的时候,命令以循环的方式执行。如果有3个参数,那么命令就会连同{}一起被执行3次。

2)结合find使用xargs

危险使用:

$find . -type f -name "*.txt" -print | xargs rm -f

这样做很危险,有可能删除不必要的文件。我们没法预测分隔find命令输出结果的定界符究竟是什么('\n'或者' ').有些文件名中包含空格符,因此xargs很可能会误认为是定界符(hell text.txt会被xargs误解为hell和text.txt)。

只要我们把find的输出作为xargs的输出作为xargs的输入,就必须将-print0与find结合使用,以字符null(‘\0’)来分隔输出。

用find匹配并列出所有的.txt文件,然后用xargs将这些文件删除:

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

这样就可以删除所有的.txt文件。xargs -0 将\0作为输入定界符。

3)统计源代码目录中所有c程序文件的行数

统计所有c程序文件的行数(Lines of Code,LOC)。

$find source_code_dir_path -type f -name "*.c" -print0 | xargs -0 wc -1

注意:有关个人源代码更多的统计信息,有个叫做SLOCCount的工具。

d)结合stdin,巧妙运用while语句和子shell

xargs只能以有限的几种方式来提供参数,而且它也不能为多组命令提供参数。要执行包含来自标准输入的多个参数的命令,使用如下:包含while循环的子shell可以用来读取参数,然后通过一种巧妙的方式执行命令:

$cat files.txt | (while read arg; do cat $arg;done)

#等同于cat files.txt | xargs -I {} cat {}

在while循环中,可以将cat $arg替换成任意数量的命令,这样我们就可以对同一个参数执行多条命令。也可以不借助管道,将输出传递给其他命令。这个技巧能够适用于各种问题场景。子shell操作符内部的多个命令可以作为一个整体来运行。

$cmd0 | (cmd1;cmd2;cmd3) |cmd4

如果cmd1时cd /,那么就会改变子shell工作目录,然而这种改变仅局限于子shell内部。cmd4则完全不知道工作目录发生了变化。


父Shell与子Shell

Login Shell

登录主机后,在执行Bash Script之前,其实我们已经处于一个BashShell中。

这个Shell叫login Shell,是将来我们执行任何Script的上层环境。又叫父SHell

其实每个帐号都可以自定义loginShell。以Linux来说,帐号的login Shell定义在/etc/passwd这个文件中。

/etc/passwd的每一行代表一个帐号,共有7个字段,之间用:隔开。

帐号:x:UID 使用者代码:GID 群组代码:用户信息:主目录:login shell路径

第二栏x为密码栏,基于系统安全考虑,编码后的密码已经被放入/etc/passwd文件中。

login Shell定义在第7个字段,如果这个字段的Shell程序不存在、不合法,或执行失败,则无法登录主机。

父Shell、子Shell

当在执行一个Shell Script时,父Shell会根据Script程序的第一行#!之后指定的Shell程序开启一个子Shell环境,然后在子Shell中执行此Shell Script。一旦子Shell中的Script执行完毕,此子Shell随即结束,回到父Shell中,不会影响父Shell原本的环境。

子Shell环境拥有与父Shell相同的环境变量、标准输入、输出、错误等。

例如:

test.sh文件内容

#!/bin/bash

cd /var/www/html

命令行:chmod +x /test.sh

命令行:./test.sh

执行完脚本后还原到父Shell,并且父Shell并没有进入/var/www/html目录。

注:这是因为当执行Shell文件时,父Shell会创建子Shell,各自独立。

如果需要使用父Shell来执行此脚本,可以使用:

命令行:. ./test.sh

注意.与./之间有一个空格符

子Shell继续开启子Shell

与父Shell启动子Shell方式一样,继续调用下去,即子Shell开启子Shell。

通过$SHLVL变量,可以知道当前所在Shell的层次

最新文章

  1. easyui的getRows和appendRow方法使用结果记录
  2. 【转】Linux下XenServer管理工具安装
  3. Linux manual中命令标号的含义
  4. MacOS10.9获取Android源码不完全笔记(2014)
  5. Jquery UI dialog 传参
  6. python matplotlib.plot画图显示中文乱码的问题
  7. Gson解析json繁杂数据
  8. sed 文件查找,替换
  9. Mac OS下安装和配置MongoDB
  10. 关于微信支付接口,curl错误代码58
  11. AngularJS $observe $watch
  12. First normal formal Second normal form
  13. HDFS高级开发培训课程之HDFS开发实例课件
  14. 《码出高效 Java开发手册》第四章 走进JVM(未整理)
  15. Dictionary<string, object>
  16. bzoj1605 / P2905 [USACO08OPEN]农场危机Crisis on the Farm
  17. margin+absolute布局:右栏固定主内容自适应 demo
  18. Spring框架学习(1)Spring简介
  19. 【面试虐菜】—— 常用SQL语句
  20. 洛谷 P4174 [NOI2006]最大获利 && 洛谷 P2762 太空飞行计划问题 (最大权闭合子图 && 最小割输出任意一组方案)

热门文章

  1. java中随机生成汉字
  2. git拉取远程分支到本地分支或者创建本地新分支
  3. 一起来学linux:SAMBA服务器搭建
  4. Android Weekly Notes Issue #255
  5. 纯CSS3左右滑动开关按钮
  6. IntelliJ IDEA 中详细图解记录如何连接MySQL数据库
  7. 搭建自己的AppRTCDemo服务器
  8. Centos7配置https,及多个https配置
  9. codeforces 705C C. Thor(模拟)
  10. Could not load the "xxx.png" image referenced from a nib in the bundle with identifier "com.xxxx"