📄 moreadv.html
字号:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><HTML><HEAD><TITLE>Complex Commands</TITLE><METANAME="GENERATOR"CONTENT="Modular DocBook HTML Stylesheet Version 1.57"><LINKREL="HOME"TITLE="Advanced Bash-Scripting Guide"HREF="index.html"><LINKREL="UP"TITLE="External Filters, Programs and Commands"HREF="external.html"><LINKREL="PREVIOUS"TITLE="External Filters, Programs and Commands"HREF="external.html"><LINKREL="NEXT"TITLE="Time / Date Commands"HREF="timedate.html"><METAHTTP-EQUIV="Content-Style-Type"CONTENT="text/css"><LINKREL="stylesheet"HREF="common/kde-common.css"TYPE="text/css"><METAHTTP-EQUIV="Content-Type"CONTENT="text/html; charset=iso-8859-1"><METAHTTP-EQUIV="Content-Language"CONTENT="en"><LINKREL="stylesheet"HREF="common/kde-localised.css"TYPE="text/css"TITLE="KDE-English"><LINKREL="stylesheet"HREF="common/kde-default.css"TYPE="text/css"TITLE="KDE-Default"></HEAD><BODYCLASS="SECT1"BGCOLOR="#FFFFFF"TEXT="#000000"LINK="#AA0000"VLINK="#AA0055"ALINK="#AA0000"STYLE="font-family: sans-serif;"><DIVCLASS="NAVHEADER"><TABLEWIDTH="100%"BORDER="0"CELLPADDING="0"CELLSPACING="0"><TR><THCOLSPAN="3"ALIGN="center">Advanced Bash-Scripting Guide: An in-depth exploration of the art of shell scripting</TH></TR><TR><TDWIDTH="10%"ALIGN="left"VALIGN="bottom"><AHREF="external.html">Prev</A></TD><TDWIDTH="80%"ALIGN="center"VALIGN="bottom">Chapter 12. External Filters, Programs and Commands</TD><TDWIDTH="10%"ALIGN="right"VALIGN="bottom"><AHREF="timedate.html">Next</A></TD></TR></TABLE><HRALIGN="LEFT"WIDTH="100%"></DIV><DIVCLASS="SECT1"><H1CLASS="SECT1"><ANAME="MOREADV">12.2. Complex Commands</A></H1><DIVCLASS="VARIABLELIST"><P><B><ANAME="CCLISTING1"></A>Commands for more advanced users</B></P><DL><DT><ANAME="FINDREF"></A><BCLASS="COMMAND">find</B></DT><DD><P>-exec <TTCLASS="REPLACEABLE"><I>COMMAND</I></TT> \;</P><P>Carries out <TTCLASS="REPLACEABLE"><I>COMMAND</I></TT> on each file that <BCLASS="COMMAND">find</B> matches. The command sequence terminates with <SPANCLASS="TOKEN">;</SPAN> (the <SPANCLASS="QUOTE">";"</SPAN> is <AHREF="escapingsection.html#ESCP">escaped</A> to make certain the shell passes it to <BCLASS="COMMAND">find</B> literally, without interpreting it as a special character).</P><P> <TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><PRECLASS="SCREEN"> <TTCLASS="PROMPT">bash$ </TT><TTCLASS="USERINPUT"><B>find ~/ -name '*.txt'</B></TT> <TTCLASS="COMPUTEROUTPUT">/home/bozo/.kde/share/apps/karm/karmdata.txt /home/bozo/misc/irmeyc.txt /home/bozo/test-scripts/1.txt</TT> </PRE></TD></TR></TABLE> </P><P><ANAME="CURLYBRACKETSREF"></A></P><P>If <TTCLASS="REPLACEABLE"><I>COMMAND</I></TT> contains <SPANCLASS="TOKEN">{}</SPAN>, then <BCLASS="COMMAND">find</B> substitutes the full path name of the selected file for <SPANCLASS="QUOTE">"{}"</SPAN>.</P><P> <TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><PRECLASS="PROGRAMLISTING"> 1 find ~/ -name 'core*' -exec rm {} \; 2 # Removes all core dump files from user's home directory.</PRE></TD></TR></TABLE> </P><P> <TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><PRECLASS="PROGRAMLISTING"> 1 find /home/bozo/projects -mtime 1 2 # Lists all files in /home/bozo/projects directory tree 3 #+ that were modified within the last day. 4 # 5 # mtime = last modification time of the target file 6 # ctime = last status change time (via 'chmod' or otherwise) 7 # atime = last access time 8 9 DIR=/home/bozo/junk_files 10 find "$DIR" -type f -atime +5 -exec rm {} \; 11 # ^^ 12 # Curly brackets are placeholder for the path name output by "find." 13 # 14 # Deletes all files in "/home/bozo/junk_files" 15 #+ that have not been accessed in at least 5 days. 16 # 17 # "-type filetype", where 18 # f = regular file 19 # d = directory, etc. 20 # (The 'find' manpage has a complete listing.)</PRE></TD></TR></TABLE> </P><P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><PRECLASS="PROGRAMLISTING"> 1 find /etc -exec grep '[0-9][0-9]*[.][0-9][0-9]*[.][0-9][0-9]*[.][0-9][0-9]*' {} \; 2 3 # Finds all IP addresses (xxx.xxx.xxx.xxx) in /etc directory files. 4 # There a few extraneous hits. How can they be filtered out? 5 6 # Perhaps by: 7 8 find /etc -type f -exec cat '{}' \; | tr -c '.[:digit:]' '\n' \ 9 | grep '^[^.][^.]*\.[^.][^.]*\.[^.][^.]*\.[^.][^.]*$' 10 # 11 # [:digit:] is one of the character classes 12 #+ introduced with the POSIX 1003.2 standard. 13 14 # Thanks, St閜hane Chazelas. </PRE></TD></TR></TABLE></P><DIVCLASS="NOTE"><TABLECLASS="NOTE"WIDTH="90%"BORDER="0"><TR><TDWIDTH="25"ALIGN="CENTER"VALIGN="TOP"><IMGSRC="common/note.png"HSPACE="5"ALT="Note"></TD><TDALIGN="LEFT"VALIGN="TOP"><P>The <TTCLASS="OPTION">-exec</TT> option to <BCLASS="COMMAND">find</B> should not be confused with the <AHREF="internal.html#EXECREF">exec</A> shell builtin.</P></TD></TR></TABLE></DIV><DIVCLASS="EXAMPLE"><HR><ANAME="EX57"></A><P><B>Example 12-3. <BCLASS="COMMAND">Badname</B>, eliminate file names in current directory containing bad characters and <AHREF="special-chars.html#WHITESPACEREF">whitespace</A>.</B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><PRECLASS="PROGRAMLISTING"> 1 #!/bin/bash 2 # badname.sh 3 # Delete filenames in current directory containing bad characters. 4 5 for filename in * 6 do 7 badname=`echo "$filename" | sed -n /[\+\{\;\"\\\=\?~\(\)\<\>\&\*\|\$]/p` 8 # badname=`echo "$filename" | sed -n '/[+{;"\=?~()<>&*|$]/p'` also works. 9 # Deletes files containing these nasties: + { ; " \ = ? ~ ( ) < > & * | $ 10 # 11 rm $badname 2>/dev/null 12 # ^^^^^^^^^^^ Error messages deep-sixed. 13 done 14 15 # Now, take care of files containing all manner of whitespace. 16 find . -name "* *" -exec rm -f {} \; 17 # The path name of the file that "find" finds replaces the "{}". 18 # The '\' ensures that the ';' is interpreted literally, as end of command. 19 20 exit 0 21 22 #--------------------------------------------------------------------- 23 # Commands below this line will not execute because of "exit" command. 24 25 # An alternative to the above script: 26 find . -name '*[+{;"\\=?~()<>&*|$ ]*' -exec rm -f '{}' \; 27 # (Thanks, S.C.)</PRE></TD></TR></TABLE><HR></DIV><DIVCLASS="EXAMPLE"><HR><ANAME="IDELETE"></A><P><B>Example 12-4. Deleting a file by its <ICLASS="EMPHASIS">inode</I> number</B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><PRECLASS="PROGRAMLISTING"> 1 #!/bin/bash 2 # idelete.sh: Deleting a file by its inode number. 3 4 # This is useful when a filename starts with an illegal character, 5 #+ such as ? or -. 6 7 ARGCOUNT=1 # Filename arg must be passed to script. 8 E_WRONGARGS=70 9 E_FILE_NOT_EXIST=71 10 E_CHANGED_MIND=72 11 12 if [ $# -ne "$ARGCOUNT" ] 13 then 14 echo "Usage: `basename $0` filename" 15 exit $E_WRONGARGS 16 fi 17 18 if [ ! -e "$1" ] 19 then 20 echo "File \""$1"\" does not exist." 21 exit $E_FILE_NOT_EXIST 22 fi 23 24 inum=`ls -i | grep "$1" | awk '{print $1}'` 25 # inum = inode (index node) number of file 26 # ----------------------------------------------------------------------- 27 # Every file has an inode, a record that holds its physical address info. 28 # ----------------------------------------------------------------------- 29 30 echo; echo -n "Are you absolutely sure you want to delete \"$1\" (y/n)? " 31 # The '-v' option to 'rm' also asks this. 32 read answer 33 case "$answer" in 34 [nN]) echo "Changed your mind, huh?" 35 exit $E_CHANGED_MIND 36 ;; 37 *) echo "Deleting file \"$1\".";; 38 esac 39 40 find . -inum $inum -exec rm {} \; 41 # ^^ 42 # Curly brackets are placeholder 43 #+ for text output by "find." 44 echo "File "\"$1"\" deleted!" 45 46 exit 0</PRE></TD></TR></TABLE><HR></DIV><P>See <AHREF="filearchiv.html#EX48">Example 12-27</A>, <AHREF="special-chars.html#EX58">Example 3-4</A>, and <AHREF="loops.html#FINDSTRING">Example 10-9</A> for scripts using <BCLASS="COMMAND">find</B>. Its manpage provides more detail on this complex and powerful command.</P></DD><DT><ANAME="XARGSREF"></A><BCLASS="COMMAND">xargs</B></DT><DD><P>A filter for feeding arguments to a command, and also a tool for assembling the commands themselves. It breaks a data stream into small enough chunks for filters and commands to process. Consider it as a powerful replacement for <AHREF="commandsub.html#BACKQUOTESREF">backquotes</A>. In situations where <AHREF="commandsub.html#COMMANDSUBREF">command substitution</A> fails with a <SPANCLASS="ERRORNAME">too many arguments</SPAN> error, substituting <BCLASS="COMMAND">xargs</B> often works. <ANAME="AEN7354"HREF="#FTN.AEN7354">[1]</A> Normally, <BCLASS="COMMAND">xargs</B> reads from <TTCLASS="FILENAME">stdin</TT> or from a pipe, but it can also be given the output of a file.</P><P>The default command for <BCLASS="COMMAND">xargs</B> is <AHREF="internal.html#ECHOREF">echo</A>. This means that input piped to <BCLASS="COMMAND">xargs</B> may have linefeeds and other whitespace characters stripped out. <TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><PRECLASS="SCREEN"> <TTCLASS="PROMPT">bash$ </TT><TTCLASS="USERINPUT"><B>ls -l</B></TT> <TTCLASS="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</TT> <TTCLASS="PROMPT">bash$ </TT><TTCLASS="USERINPUT"><B>ls -l | xargs</B></TT> <TTCLASS="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</TT> <TTCLASS="PROMPT">bash$ </TT><TTCLASS="USERINPUT"><B>find ~/mail -type f | xargs grep "Linux"</B></TT> <TTCLASS="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 . . .</TT> </PRE></TD></TR></TABLE> </P><P><TTCLASS="USERINPUT"><B>ls | xargs -p -l gzip</B></TT> <AHREF="filearchiv.html#GZIPREF">gzips</A> every file in current directory, one at a time, prompting before each operation.</P><DIVCLASS="TIP"><TABLECLASS="TIP"WIDTH="90%"BORDER="0"><TR><TDWIDTH="25"ALIGN="CENTER"VALIGN="TOP"><IMGSRC="common/tip.png"HSPACE="5"ALT="Tip"></TD><TDALIGN="LEFT"VALIGN="TOP"><P>An interesting <BCLASS="COMMAND">xargs</B> option is <TTCLASS="OPTION">-n <TTCLASS="REPLACEABLE"><I>NN</I></TT></TT>, which limits to <TTCLASS="REPLACEABLE"><I>NN</I></TT> the number of arguments passed.</P><P><TTCLASS="USERINPUT"><B>ls | xargs -n 8 echo</B></TT> lists the files in the current directory in <TTCLASS="LITERAL">8</TT> columns.</P></TD></TR></TABLE></DIV><DIVCLASS="TIP"><TABLECLASS="TIP"WIDTH="90%"BORDER="0"><TR><TDWIDTH="25"ALIGN="CENTER"VALIGN="TOP"><IMGSRC="common/tip.png"HSPACE="5"ALT="Tip"></TD><TDALIGN="LEFT"VALIGN="TOP"><P>Another useful option is <TTCLASS="OPTION">-0</TT>, in combination with <BCLASS="COMMAND">find -print0</B> or <BCLASS="COMMAND">grep -lZ</B>. This allows handling arguments containing whitespace or quotes.</P><P> <TTCLASS="USERINPUT"><B>find / -type f -print0 | xargs -0 grep -liwZ GUI | xargs -0 rm -f</B></TT> </P><P> <TTCLASS="USERINPUT"><B>grep -rliwZ GUI / | xargs -0 rm -f</B></TT> </P><P>Either of the above will remove any file containing <SPANCLASS="QUOTE">"GUI"</SPAN>. <ICLASS="EMPHASIS">(Thanks, S.C.)</I></P></TD></TR></TABLE></DIV><DIVCLASS="EXAMPLE"><HR><ANAME="EX41"></A><P><B>Example 12-5. Logfile: Using <BCLASS="COMMAND">xargs</B> to monitor system log</B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><PRECLASS="PROGRAMLISTING"> 1 #!/bin/bash 2 3 # Generates a log file in current directory 4 # from the tail end of /var/log/messages. 5 6 # Note: /var/log/messages must be world readable 7 # if this script invoked by an ordinary user. 8 # #root chmod 644 /var/log/messages 9 10 LINES=5 11 12 ( date; uname -a ) >>logfile 13 # Time and machine name 14 echo --------------------------------------------------------------------- >>logfile 15 tail -$LINES /var/log/messages | xargs | fmt -s >>logfile
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -