2019-04-21 11:50:48 +08:00

129 lines
6.3 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<h1 id="xargs">xargs</h1>
<p>给其他命令传递参数的一个过滤器</p>
<h2 id="补充说明">补充说明</h2>
<p><strong>xargs 命令</strong> 是给其他命令传递参数的一个过滤器也是组合多个命令的一个工具。它擅长将标准输入数据转换成命令行参数xargs 能够处理管道或者 stdin 并将其转换成特定命令的命令参数。xargs 也可以将单行或多行文本输入转换为其他格式例如多行变单行单行变多行。xargs 的默认命令是 echo空格是默认定界符。这意味着通过管道传递给 xargs 的输入将会包含换行和空白,不过通过 xargs 的处理换行和空白将被空格取代。xargs 是构建单行命令的重要组件之一。</p>
<h3 id="xargs-命令用法">xargs 命令用法</h3>
<p>xargs 用作替换工具,读取输入数据重新格式化后输出。</p>
<p>定义一个测试文件,内有多行文本数据:</p>
<pre><code class="language-bash">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
</code></pre>
<p>多行输入单行输出:</p>
<pre><code class="language-bash">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</code></pre>
<h4 id="使用--n-进行多行输出">使用 -n 进行多行输出</h4>
<p><strong>-n 选项</strong> 多行输出:</p>
<pre><code class="language-bash">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</code></pre>
<h4 id="使用--d-分割输入">使用 -d 分割输入</h4>
<p><strong>-d 选项</strong> 可以自定义一个定界符:</p>
<pre><code class="language-bash">echo &quot;nameXnameXnameXname&quot; | xargs -dX
name name name name</code></pre>
<p>结合 <strong>-n 选项</strong> 使用:</p>
<pre><code class="language-bash">echo &quot;nameXnameXnameXname&quot; | xargs -dX -n2
name name
name name</code></pre>
<h4 id="读取-stdin">读取 stdin</h4>
<p><strong>读取 stdin将格式化后的参数传递给命令</strong></p>
<p>假设一个命令为 sk.sh 和一个保存参数的文件 arg.txt</p>
<pre><code class="language-bash">#!/bin/bash
#sk.sh 命令内容,打印出所有参数。
echo $*
</code></pre>
<p>arg.txt 文件内容:</p>
<pre><code class="language-bash">cat arg.txt
aaa
bbb
ccc
</code></pre>
<h4 id="结合--i-选项">结合 -I 选项</h4>
<p>xargs 的一个 <strong>选项 -I</strong> ,使用 -I 指定一个替换字符串{},这个字符串在 xargs 扩展时会被替换掉,当 -I 与 xargs 结合使用,每一个参数命令都会被执行一次:</p>
<pre><code class="language-bash">cat arg.txt | xargs -I {} ./sk.sh -p {} -l
-p aaa -l
-p bbb -l
-p ccc -l
</code></pre>
<p>复制所有图片文件到 /data/images 目录下:</p>
<pre><code class="language-bash">ls *.jpg | xargs -n1 -I cp {} /data/images</code></pre>
<h4 id="结合-find-命令使用">结合 find 命令使用</h4>
<p><strong>xargs 结合 find 使用</strong></p>
<p>用 rm 删除太多的文件时候,可能得到一个错误信息:<code>/bin/rm Argument list too long</code>. 用 <code>xargs</code> 去避免这个问题:</p>
<pre><code class="language-bash">find . -type f -name &quot;*.log&quot; -print0 | xargs -0 rm -f</code></pre>
<p>xargs -0 将 <code>\0</code> 作为定界符。</p>
<p>统计一个源代码目录中所有 php 文件的行数:</p>
<pre><code class="language-bash">find . -type f -name &quot;*.php&quot; -print0 | xargs -0 wc -l</code></pre>
<p>查找所有的 jpg 文件,并且压缩它们:</p>
<pre><code class="language-bash">find . -type f -name &quot;*.jpg&quot; -print | xargs tar -czvf images.tar.gz
</code></pre>
<h4 id="打印出执行的命令">打印出执行的命令</h4>
<p>结合 <code>-t</code> 选项可以打印出 <code>xargs</code> 执行的命令</p>
<pre><code class="language-bash">ls | xargs -t -I{} echo {}</code></pre>
<p>会输出当前目录下的文件列表和执行的 echo 命令</p>
<h4 id="使用--p-选项确认执行的命令">使用 -p 选项确认执行的命令</h4>
<p><code>-p</code> 选项会在执行每一个命令时弹出确认,当你需要非常准确的确认每一次操作时可以使用 <code>-p</code> 参数,比如,查找当前目录下 <code>.log</code> 文件,每一次删除都需要确认:</p>
<pre><code class="language-bash">find . -maxdepth 1 -name &quot;*.log&quot; | xargs -p -I{} rm {}</code></pre>
<h4 id="执行多个命令">执行多个命令</h4>
<p>使用 <code>-I</code> 选项可以让 <code>xargs</code> 执行多个命令</p>
<pre><code class="language-bash">cat foo.txt
one
two
three
cat foo.txt | xargs -I % sh -c &#39;echo %; mkdir %&#39;
one
two
three
ls
one two three</code></pre>
<h4 id="其他应用">其他应用</h4>
<p><strong>xargs 其他应用</strong></p>
<p>假如你有一个文件包含了很多你希望下载的 URL你能够使用 xargs 下载所有链接:</p>
<pre><code class="language-bash">cat url-list.txt | xargs wget -c</code></pre>
<h3 id="子-shellsubshells">子 ShellSubshells</h3>
<p>运行一个 shell 脚本时会启动另一个命令解释器.,就好像你的命令是在命令行提示下被解释的一样,类似于批处理文件里的一系列命令。每个 shell 脚本有效地运行在父 shell(parent shell) 的一个子进程里。这个父 shell 是指在一个控制终端或在一个 xterm 窗口中给你命令指示符的进程。</p>
<pre><code class="language-bash">cmd1 | ( cmd2; cmd3; cmd4 ) | cmd5</code></pre>
<p>如果 cmd2 是 cd /,那么就会改变子 Shell 的工作目录,这种改变只是局限于子 shell 内部cmd5 则完全不知道工作目录发生的变化。子 shell 是嵌在圆括号 () 内部的命令序列,子 Shell 内部定义的变量为局部变量。</p>
<p>子 shell 可用于为一组命令设定临时的环境变量:</p>
<pre><code class="language-bash">COMMAND1
COMMAND2
COMMAND3
(
IFS=:
PATH=/bin
unset TERMINFO
set -C
shift 5
COMMAND4
COMMAND5
exit 3 # 只是从子 shell 退出。
)
# 父 shell 不受影响,变量值没有更改。
COMMAND6
COMMAND7</code></pre>
<h2 id="reference">reference</h2>
<ul>
<li><a href="https://shapeshed.com/unix-xargs/" class="uri">https://shapeshed.com/unix-xargs/</a></li>
</ul>
<!-- Linux 命令行搜索引擎https://jaywcjlove.github.io/linux-command/ -->