⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 moreadv.html

📁 BASH Shell 编程 经典教程 《高级SHELL脚本编程》中文版
💻 HTML
📖 第 1 页 / 共 2 页
字号:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><HTML><HEAD><TITLE>复杂命令</TITLE><METANAME="GENERATOR"CONTENT="Modular DocBook HTML Stylesheet Version 1.79"><LINKREL="HOME"TITLE="高级Bash脚本编程指南"HREF="index.html"><LINKREL="UP"TITLE="外部过滤器, 程序和命令"HREF="external.html"><LINKREL="PREVIOUS"TITLE="基本命令"HREF="basic.html"><LINKREL="NEXT"TITLE="时间/日期 命令"HREF="timedate.html"></HEAD><BODYCLASS="SECT1"BGCOLOR="#FFFFFF"TEXT="#000000"LINK="#0000FF"VLINK="#840084"ALINK="#0000FF"><DIVCLASS="NAVHEADER"><TABLESUMMARY="Header navigation table"WIDTH="100%"BORDER="0"CELLPADDING="0"CELLSPACING="0"><TR><THCOLSPAN="3"ALIGN="center">高级Bash脚本编程指南: 一本深入学习shell脚本艺术的书籍</TH></TR><TR><TDWIDTH="10%"ALIGN="left"VALIGN="bottom"><AHREF="basic.html"ACCESSKEY="P">前一页</A></TD><TDWIDTH="80%"ALIGN="center"VALIGN="bottom">12. 外部过滤器, 程序和命令</TD><TDWIDTH="10%"ALIGN="right"VALIGN="bottom"><AHREF="timedate.html"ACCESSKEY="N">下一页</A></TD></TR></TABLE><HRALIGN="LEFT"WIDTH="100%"></DIV><DIVCLASS="SECT1"><H1CLASS="SECT1"><ANAME="MOREADV">12.2. 复杂命令</A></H1><P></P><DIVCLASS="VARIABLELIST"><P><B><ANAME="CCLISTING1"></A>更高级的用户命令</B></P><DL><DT><ANAME="FINDREF"></A><BCLASS="COMMAND">find</B></DT><DD><P>-exec <TTCLASS="REPLACEABLE"><I>COMMAND</I></TT> \;</P><P>在每一个<BCLASS="COMMAND">find</B>匹配到的文件执行<TTCLASS="REPLACEABLE"><I>COMMAND</I></TT>命令. 			命令序列以<SPANCLASS="TOKEN">;</SPAN>结束(<SPANCLASS="QUOTE">";"</SPAN>是<AHREF="escapingsection.html#ESCP">转义符</A>以保证shll传递到<BCLASS="COMMAND">find</B>命令中的字符不会被解释为其他的特殊字符). </P><P>	      <TABLEBORDER="1"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="SCREEN"><SAMPCLASS="PROMPT">bash$ </SAMP><KBDCLASS="USERINPUT">find ~/ -name '*.txt'</KBD><SAMPCLASS="COMPUTEROUTPUT">/home/bozo/.kde/share/apps/karm/karmdata.txt /home/bozo/misc/irmeyc.txt /home/bozo/test-scripts/1.txt</SAMP>	      </PRE></FONT></TD></TR></TABLE>	  </P><P><ANAME="CURLYBRACKETSREF"></A></P><P>如果<TTCLASS="REPLACEABLE"><I>COMMAND</I></TT>中包含<SPANCLASS="TOKEN">{}</SPAN>, 				那么<BCLASS="COMMAND">find</B>命令将会用所有匹配文件的路径名来替换<SPANCLASS="QUOTE">"{}"</SPAN>. </P><P>          <TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="PROGRAMLISTING">  1&nbsp;find ~/ -name 'core*' -exec rm {} \;  2&nbsp;# 从用户的 home 目录中删除所有的 core dump文件. </PRE></FONT></TD></TR></TABLE>	  </P><P>	  <TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="PROGRAMLISTING">  1&nbsp;find /home/bozo/projects -mtime 1  2&nbsp;#  列出最后一天被修改的  3&nbsp;#+ 在/home/bozo/projects目录树下的所有文件.  4&nbsp;#  5&nbsp;#  mtime = 目标文件最后修改的时间  6&nbsp;#  ctime = 修改后的最后状态(通过'chmod'或其他方法)  7&nbsp;#  atime = 最后访问时间  8&nbsp;  9&nbsp;DIR=/home/bozo/junk_files 10&nbsp;find "$DIR" -type f -atime +5 -exec rm {} \; 11&nbsp;#                                      ^^ 12&nbsp;#  大括号就是"find"命令用来替换目录的地方. 13&nbsp;# 14&nbsp;#  删除至少5天内没被访问过的 15&nbsp;#+ "/home/bozo/junk_files" 中的所有文件. 16&nbsp;# 17&nbsp;#  "-type filetype", where 18&nbsp;#  f = regular file 19&nbsp;#  d = directory, etc. 20&nbsp;#  ('find' 命令的man页包含有完整的选项列表.) </PRE></FONT></TD></TR></TABLE>          </P><P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="PROGRAMLISTING">  1&nbsp;find /etc -exec grep '[0-9][0-9]*[.][0-9][0-9]*[.][0-9][0-9]*[.][0-9][0-9]*' {} \;  2&nbsp;  3&nbsp;# 在 /etc 目录中的文件找到所所有包含 IP 地址(xxx.xxx.xxx.xxx) 的文件.  4&nbsp;# 可能会查找到一些多余的匹配. 我们如何去掉它们呢?  5&nbsp;  6&nbsp;# 或许可以使用如下方法:  7&nbsp;  8&nbsp;find /etc -type f -exec cat '{}' \; | tr -c '.[:digit:]' '\n' \  9&nbsp;| grep '^[^.][^.]*\.[^.][^.]*\.[^.][^.]*\.[^.][^.]*$' 10&nbsp;# 11&nbsp;#  [:digit:] 是一种字符类. 12&nbsp;#+ 关于字符类的介绍请参考 POSIX 1003.2 标准化文档.  13&nbsp; 14&nbsp;# 感谢, Stephane Chazelas. </PRE></FONT></TD></TR></TABLE></P><DIVCLASS="NOTE"><P></P><TABLECLASS="NOTE"WIDTH="90%"BORDER="0"><TR><TDWIDTH="25"ALIGN="CENTER"VALIGN="TOP"><IMGSRC="./images/note.gif"HSPACE="5"ALT="Note"></TD><TDALIGN="LEFT"VALIGN="TOP"><P><BCLASS="COMMAND">find</B>命令的<CODECLASS="OPTION">-exec</CODE>选项不应该与shell中的内建命令<AHREF="internal.html#EXECREF">exec</A>相混淆. </P></TD></TR></TABLE></DIV><DIVCLASS="EXAMPLE"><HR><ANAME="EX57"></A><P><B>例子 12-3. <BCLASS="COMMAND">糟糕的文件名</B>, 删除当前目录下文件名中包含一些糟糕字符(包括<AHREF="special-chars.html#WHITESPACEREF">空白</A>的文件.</B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="PROGRAMLISTING">  1&nbsp;#!/bin/bash  2&nbsp;# badname.sh  3&nbsp;# 删除当前目录下文件名中包含一些特殊字符的文件.(这些特殊字符指的是不应该出现在文件名中的字符)  4&nbsp;  5&nbsp;for filename in *  6&nbsp;do  7&nbsp;  badname=`echo "$filename" | sed -n /[\+\{\;\"\\\=\?~\(\)\&#60;\&#62;\&#38;\*\|\$]/p`  8&nbsp;# badname=`echo "$filename" | sed -n '/[+{;"\=?~()&#60;&#62;&#38;*|$]/p'`  这句也行.  9&nbsp;# 删除文件名包含这些字符的文件:     + { ; " \ = ? ~ ( ) &#60; &#62; &#38; * | $ 10&nbsp;# 11&nbsp;  rm $badname 2&#62;/dev/null 12&nbsp;#             ^^^^^^^^^^^ 错误消息将被抛弃. 13&nbsp;done 14&nbsp; 15&nbsp;# 现在, 处理文件名中以任何方式包含空白的文件. 16&nbsp;find . -name "* *" -exec rm -f {} \; 17&nbsp;# "find"命令匹配到的目录名将替换到"{}"的位置. 18&nbsp;# '\'是为了保证';'被正确的转义, 并且放到命令的结尾. 19&nbsp; 20&nbsp;exit 0 21&nbsp; 22&nbsp;#--------------------------------------------------------------------- 23&nbsp;# 这行下边的命令将不会运行, 因为有 "exit" 命令. 24&nbsp; 25&nbsp;# 下边这句可以用来替换上边的脚本:  26&nbsp;find . -name '*[+{;"\\=?~()&#60;&#62;&#38;*|$ ]*' -exec rm -f '{}' \; 27&nbsp;# (感谢, S.C.)</PRE></FONT></TD></TR></TABLE><HR></DIV><DIVCLASS="EXAMPLE"><HR><ANAME="IDELETE"></A><P><B>例子 12-4. 通过文件的<EM>inode</EM>号来删除文件</B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="PROGRAMLISTING">  1&nbsp;#!/bin/bash  2&nbsp;# idelete.sh: 通过文件的inode号来删除文件.  3&nbsp;  4&nbsp;#  当文件名以一个非法字符开头的时候, 这就非常有用了,  5&nbsp;#+ 比如 ? 或 -.  6&nbsp;  7&nbsp;ARGCOUNT=1                      # 文件名参数必须被传递到脚本中.  8&nbsp;E_WRONGARGS=70  9&nbsp;E_FILE_NOT_EXIST=71 10&nbsp;E_CHANGED_MIND=72 11&nbsp; 12&nbsp;if [ $# -ne "$ARGCOUNT" ] 13&nbsp;then 14&nbsp;  echo "Usage: `basename $0` filename" 15&nbsp;  exit $E_WRONGARGS 16&nbsp;fi   17&nbsp; 18&nbsp;if [ ! -e "$1" ] 19&nbsp;then 20&nbsp;  echo "File \""$1"\" does not exist." 21&nbsp;  exit $E_FILE_NOT_EXIST 22&nbsp;fi   23&nbsp; 24&nbsp;inum=`ls -i | grep "$1" | awk '{print $1}'` 25&nbsp;# inum = inode 文件的(索引节点)号. 26&nbsp;# -------------------------------------------------------- 27&nbsp;# 每个文件都有一个inode号, 这个号用来记录文件物理地址信息. 28&nbsp;# -------------------------------------------------------- 29&nbsp; 30&nbsp;echo; echo -n "Are you absolutely sure you want to delete \"$1\" (y/n)? " 31&nbsp;# 'rm' 命令的 '-v' 选项得询问也会出现这句话. 32&nbsp;read answer 33&nbsp;case "$answer" in 34&nbsp;[nN]) echo "Changed your mind, huh?" 35&nbsp;      exit $E_CHANGED_MIND 36&nbsp;      ;; 37&nbsp;*)    echo "Deleting file \"$1\".";; 38&nbsp;esac 39&nbsp; 40&nbsp;find . -inum $inum -exec rm {} \; 41&nbsp;#                           ^^ 42&nbsp;#        大括号就是"find"命令 43&nbsp;#+       用来替换文本输出的地方. 44&nbsp;echo "File "\"$1"\" deleted!" 45&nbsp; 46&nbsp;exit 0</PRE></FONT></TD></TR></TABLE><HR></DIV><P>请参考<AHREF="filearchiv.html#EX48">例子 12-27</A>, <AHREF="special-chars.html#EX58">例子 3-4</A>,		和<AHREF="loops1.html#FINDSTRING">例子 10-9</A> 这些例子展示了如何使用<BCLASS="COMMAND">find</B>命令. 		对于这个强大而又复杂的命令来说, 查看man页可以获得更多的细节. 	      </P></DD><DT><ANAME="XARGSREF"></A><BCLASS="COMMAND">xargs</B></DT><DD><P>这是给命令传递参数的一个过滤器, 也是组合多个命令的一个工具. 			  它把一个数据流分割为一些足够小的块, 			  以方便过滤器和命令进行处理. 			  由此这个命令也是<AHREF="commandsub.html#BACKQUOTESREF">后置引用</A>的一个强有力的替换. 			  当在一般情况下使用<SPANCLASS="ERRORNAME">过多参数</SPAN>的<AHREF="commandsub.html#COMMANDSUBREF">命令替换</A>都会产生失败的现象, 			  这时候使用<BCLASS="COMMAND">xargs</B>命令来替换, 一般都能成功. 			  <ANAME="AEN7492"HREF="#FTN.AEN7492"><SPANCLASS="footnote">[1]</SPAN></A>	      一般的, <BCLASS="COMMAND">xargs</B>从<TTCLASS="FILENAME">stdin</TT>或者管道中读取数据, 	      但是它也能够从文件的输出中读取数据. </P><P><BCLASS="COMMAND">xargs</B>的默认命令是<AHREF="internal.html#ECHOREF">echo</A>. 		  这意味着通过管道传递给<BCLASS="COMMAND">xargs</B>的输入将会包含换行和空白, 		  不过通过<BCLASS="COMMAND">xargs</B>的处理, 		  换行和空白将被空格取代.	      	      <TABLEBORDER="1"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="SCREEN"><SAMPCLASS="PROMPT">bash$ </SAMP><KBDCLASS="USERINPUT">ls -l</KBD><SAMPCLASS="COMPUTEROUTPUT">total 0 -rw-rw-r--    1 bozo  bozo         0 Jan 29 23:58 file1 -rw-rw-r--    1 bozo  bozo         0 Jan 29 23:58 file2</SAMP><SAMPCLASS="PROMPT">bash$ </SAMP><KBDCLASS="USERINPUT">ls -l | xargs</KBD><SAMPCLASS="COMPUTEROUTPUT">total 0 -rw-rw-r-- 1 bozo bozo 0 Jan 29 23:58 file1 -rw-rw-r-- 1 bozo bozo 0 Jan 29 23:58 file2</SAMP><SAMPCLASS="PROMPT">bash$ </SAMP><KBDCLASS="USERINPUT">find ~/mail -type f | xargs grep "Linux"</KBD><SAMPCLASS="COMPUTEROUTPUT">./misc:User-Agent: slrn/0.9.8.1 (Linux) ./sent-mail-jul-2005: hosted by the Linux Documentation Project. ./sent-mail-jul-2005: (Linux Documentation Project Site, rtf version) ./sent-mail-jul-2005: Subject: Criticism of Bozo's Windows/Linux article ./sent-mail-jul-2005: while mentioning that the Linux ext2/ext3 filesystem . . .</SAMP>	      </PRE></FONT></TD></TR></TABLE>	      	      </P><P><KBDCLASS="USERINPUT">ls | xargs -p -l gzip</KBD> 使用<AHREF="filearchiv.html#GZIPREF">gzips</A>压缩当前目录下的每个文件, 		   每次压缩一个, 并且在每次压缩前都提示用户. </P><DIVCLASS="TIP"><P></P><TABLECLASS="TIP"WIDTH="90%"BORDER="0"><TR><TDWIDTH="25"ALIGN="CENTER"VALIGN="TOP"><IMGSRC="./images/tip.gif"HSPACE="5"ALT="Tip"></TD><TDALIGN="LEFT"VALIGN="TOP"><P>一个有趣的<BCLASS="COMMAND">xargs</B>选项是<CODECLASS="OPTION">-n <TTCLASS="REPLACEABLE"><I>NN</I></TT></CODE>,	      <TTCLASS="REPLACEABLE"><I>NN</I></TT>用来限制每次传递进来参数的个数. </P><P><KBDCLASS="USERINPUT">ls | xargs -n 8 echo</KBD>以每行<TTCLASS="LITERAL">8</TT>列的形式列出当前目录下的所有文件. </P></TD></TR></TABLE></DIV><DIVCLASS="TIP"><P></P><TABLECLASS="TIP"WIDTH="90%"BORDER="0"><TR><TDWIDTH="25"ALIGN="CENTER"VALIGN="TOP"><IMGSRC="./images/tip.gif"HSPACE="5"ALT="Tip"></TD><TDALIGN="LEFT"VALIGN="TOP"><P>另一个有用的选项是<CODECLASS="OPTION">-0</CODE>, 			使用<BCLASS="COMMAND">find -print0</B><BCLASS="COMMAND">grep -lZ</B>这两种组合方式. 这允许处理包含空白或引号的参数. </P><P>	    <KBDCLASS="USERINPUT">find / -type f -print0 | xargs -0 grep -liwZ GUI | xargs -0 rm -f</KBD>	    </P><P>	    <KBDCLASS="USERINPUT">grep -rliwZ GUI / | xargs -0 rm -f</KBD>	    </P><P>上边两行都可用来删除任何包含<SPANCLASS="QUOTE">"GUI"</SPAN>的文件.	      <EM>(感谢, S.C.)</EM></P></TD></TR></TABLE></DIV><DIVCLASS="EXAMPLE"><HR><ANAME="EX41"></A><P><B>例子 12-5. Logfile: 使用<BCLASS="COMMAND">xargs</B>来监控系统log</B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="PROGRAMLISTING">  1&nbsp;#!/bin/bash  2&nbsp;  3&nbsp;# 从/var/log/messagesGenerates的尾部开始  4&nbsp;# 产生当前目录下的一个lof文件.  5&nbsp;  6&nbsp;# 注意: 如果这个脚本被一个一般用户调用的话,  7&nbsp;# /var/log/messages 必须是全部可读的.  8&nbsp;#         #root chmod 644 /var/log/messages  9&nbsp; 10&nbsp;LINES=5 11&nbsp; 12&nbsp;( date; uname -a ) &#62;&#62;logfile 13&nbsp;# 时间和机器名 14&nbsp;echo --------------------------------------------------------------------- &#62;&#62;logfile 15&nbsp;tail -$LINES /var/log/messages | xargs |  fmt -s &#62;&#62;logfile 16&nbsp;echo &#62;&#62;logfile 17&nbsp;echo &#62;&#62;logfile 18&nbsp; 19&nbsp;exit 0 20&nbsp; 21&nbsp;#  注意: 22&nbsp;#  -----

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -