1787 lines
29 KiB
HTML
1787 lines
29 KiB
HTML
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
||
<HTML
|
||
><HEAD
|
||
><TITLE
|
||
>Complex Commands</TITLE
|
||
><META
|
||
NAME="GENERATOR"
|
||
CONTENT="Modular DocBook HTML Stylesheet Version 1.7"><LINK
|
||
REL="HOME"
|
||
TITLE="Advanced Bash-Scripting Guide"
|
||
HREF="index.html"><LINK
|
||
REL="UP"
|
||
TITLE="External Filters, Programs and Commands"
|
||
HREF="external.html"><LINK
|
||
REL="PREVIOUS"
|
||
TITLE="Basic Commands"
|
||
HREF="basic.html"><LINK
|
||
REL="NEXT"
|
||
TITLE="Time / Date Commands"
|
||
HREF="timedate.html"></HEAD
|
||
><BODY
|
||
CLASS="SECT1"
|
||
BGCOLOR="#FFFFFF"
|
||
TEXT="#000000"
|
||
LINK="#0000FF"
|
||
VLINK="#840084"
|
||
ALINK="#0000FF"
|
||
><DIV
|
||
CLASS="NAVHEADER"
|
||
><TABLE
|
||
SUMMARY="Header navigation table"
|
||
WIDTH="100%"
|
||
BORDER="0"
|
||
CELLPADDING="0"
|
||
CELLSPACING="0"
|
||
><TR
|
||
><TH
|
||
COLSPAN="3"
|
||
ALIGN="center"
|
||
>Advanced Bash-Scripting Guide: </TH
|
||
></TR
|
||
><TR
|
||
><TD
|
||
WIDTH="10%"
|
||
ALIGN="left"
|
||
VALIGN="bottom"
|
||
><A
|
||
HREF="basic.html"
|
||
ACCESSKEY="P"
|
||
>Prev</A
|
||
></TD
|
||
><TD
|
||
WIDTH="80%"
|
||
ALIGN="center"
|
||
VALIGN="bottom"
|
||
>Chapter 16. External Filters, Programs and Commands</TD
|
||
><TD
|
||
WIDTH="10%"
|
||
ALIGN="right"
|
||
VALIGN="bottom"
|
||
><A
|
||
HREF="timedate.html"
|
||
ACCESSKEY="N"
|
||
>Next</A
|
||
></TD
|
||
></TR
|
||
></TABLE
|
||
><HR
|
||
ALIGN="LEFT"
|
||
WIDTH="100%"></DIV
|
||
><DIV
|
||
CLASS="SECT1"
|
||
><H1
|
||
CLASS="SECT1"
|
||
><A
|
||
NAME="MOREADV"
|
||
></A
|
||
>16.2. Complex Commands</H1
|
||
><P
|
||
></P
|
||
><DIV
|
||
CLASS="VARIABLELIST"
|
||
><P
|
||
><B
|
||
><A
|
||
NAME="CCLISTING1"
|
||
></A
|
||
>Commands for more advanced users</B
|
||
></P
|
||
><DL
|
||
><DT
|
||
><A
|
||
NAME="FINDREF"
|
||
></A
|
||
><B
|
||
CLASS="COMMAND"
|
||
>find</B
|
||
></DT
|
||
><DD
|
||
><P
|
||
><A
|
||
NAME="FINDREF0"
|
||
></A
|
||
></P
|
||
><P
|
||
>-exec <TT
|
||
CLASS="REPLACEABLE"
|
||
><I
|
||
>COMMAND</I
|
||
></TT
|
||
> \;</P
|
||
><P
|
||
>Carries out <TT
|
||
CLASS="REPLACEABLE"
|
||
><I
|
||
>COMMAND</I
|
||
></TT
|
||
> on
|
||
each file that <B
|
||
CLASS="COMMAND"
|
||
>find</B
|
||
> matches. The
|
||
command sequence terminates with <SPAN
|
||
CLASS="TOKEN"
|
||
>;</SPAN
|
||
> (the
|
||
<SPAN
|
||
CLASS="QUOTE"
|
||
>";"</SPAN
|
||
> is <A
|
||
HREF="escapingsection.html#ESCP"
|
||
>escaped</A
|
||
> to
|
||
make certain the shell passes it to <B
|
||
CLASS="COMMAND"
|
||
>find</B
|
||
>
|
||
literally, without interpreting it as a special character).</P
|
||
><P
|
||
> <TABLE
|
||
BORDER="1"
|
||
BGCOLOR="#E0E0E0"
|
||
WIDTH="90%"
|
||
><TR
|
||
><TD
|
||
><FONT
|
||
COLOR="#000000"
|
||
><PRE
|
||
CLASS="SCREEN"
|
||
><TT
|
||
CLASS="PROMPT"
|
||
>bash$ </TT
|
||
><TT
|
||
CLASS="USERINPUT"
|
||
><B
|
||
>find ~/ -name '*.txt'</B
|
||
></TT
|
||
>
|
||
<TT
|
||
CLASS="COMPUTEROUTPUT"
|
||
>/home/bozo/.kde/share/apps/karm/karmdata.txt
|
||
/home/bozo/misc/irmeyc.txt
|
||
/home/bozo/test-scripts/1.txt</TT
|
||
>
|
||
</PRE
|
||
></FONT
|
||
></TD
|
||
></TR
|
||
></TABLE
|
||
>
|
||
</P
|
||
><P
|
||
><A
|
||
NAME="CURLYBRACKETSREF"
|
||
></A
|
||
></P
|
||
><P
|
||
>If <TT
|
||
CLASS="REPLACEABLE"
|
||
><I
|
||
>COMMAND</I
|
||
></TT
|
||
> contains
|
||
<SPAN
|
||
CLASS="TOKEN"
|
||
>{}</SPAN
|
||
>, then <B
|
||
CLASS="COMMAND"
|
||
>find</B
|
||
>
|
||
substitutes the full path name of the selected file for
|
||
<SPAN
|
||
CLASS="QUOTE"
|
||
>"{}"</SPAN
|
||
>.</P
|
||
><P
|
||
> <TABLE
|
||
BORDER="0"
|
||
BGCOLOR="#E0E0E0"
|
||
WIDTH="90%"
|
||
><TR
|
||
><TD
|
||
><FONT
|
||
COLOR="#000000"
|
||
><PRE
|
||
CLASS="PROGRAMLISTING"
|
||
>find ~/ -name 'core*' -exec rm {} \;
|
||
# Removes all core dump files from user's home directory.</PRE
|
||
></FONT
|
||
></TD
|
||
></TR
|
||
></TABLE
|
||
>
|
||
</P
|
||
><P
|
||
><TABLE
|
||
BORDER="0"
|
||
BGCOLOR="#E0E0E0"
|
||
WIDTH="90%"
|
||
><TR
|
||
><TD
|
||
><FONT
|
||
COLOR="#000000"
|
||
><PRE
|
||
CLASS="PROGRAMLISTING"
|
||
>find /home/bozo/projects -mtime -1
|
||
# ^ Note minus sign!
|
||
# Lists all files in /home/bozo/projects directory tree
|
||
#+ that were modified within the last day (current_day - 1).
|
||
#
|
||
find /home/bozo/projects -mtime 1
|
||
# Same as above, but modified *exactly* one day ago.
|
||
#
|
||
# mtime = last modification time of the target file
|
||
# ctime = last status change time (via 'chmod' or otherwise)
|
||
# atime = last access time
|
||
|
||
DIR=/home/bozo/junk_files
|
||
find "$DIR" -type f -atime +5 -exec rm {} \;
|
||
# ^ ^^
|
||
# Curly brackets are placeholder for the path name output by "find."
|
||
#
|
||
# Deletes all files in "/home/bozo/junk_files"
|
||
#+ that have not been accessed in *at least* 5 days (plus sign ... +5).
|
||
#
|
||
# "-type filetype", where
|
||
# f = regular file
|
||
# d = directory
|
||
# l = symbolic link, etc.
|
||
#
|
||
# (The 'find' manpage and info page have complete option listings.)</PRE
|
||
></FONT
|
||
></TD
|
||
></TR
|
||
></TABLE
|
||
>
|
||
</P
|
||
><P
|
||
><TABLE
|
||
BORDER="0"
|
||
BGCOLOR="#E0E0E0"
|
||
WIDTH="90%"
|
||
><TR
|
||
><TD
|
||
><FONT
|
||
COLOR="#000000"
|
||
><PRE
|
||
CLASS="PROGRAMLISTING"
|
||
>find /etc -exec grep '[0-9][0-9]*[.][0-9][0-9]*[.][0-9][0-9]*[.][0-9][0-9]*' {} \;
|
||
|
||
# Finds all IP addresses (xxx.xxx.xxx.xxx) in /etc directory files.
|
||
# There a few extraneous hits. Can they be filtered out?
|
||
|
||
# Possibly by:
|
||
|
||
find /etc -type f -exec cat '{}' \; | tr -c '.[:digit:]' '\n' \
|
||
| grep '^[^.][^.]*\.[^.][^.]*\.[^.][^.]*\.[^.][^.]*$'
|
||
#
|
||
# [:digit:] is one of the character classes
|
||
#+ introduced with the POSIX 1003.2 standard.
|
||
|
||
# Thanks, St<53>phane Chazelas. </PRE
|
||
></FONT
|
||
></TD
|
||
></TR
|
||
></TABLE
|
||
></P
|
||
><DIV
|
||
CLASS="NOTE"
|
||
><P
|
||
></P
|
||
><TABLE
|
||
CLASS="NOTE"
|
||
WIDTH="90%"
|
||
BORDER="0"
|
||
><TR
|
||
><TD
|
||
WIDTH="25"
|
||
ALIGN="CENTER"
|
||
VALIGN="TOP"
|
||
><IMG
|
||
SRC="../images/note.gif"
|
||
HSPACE="5"
|
||
ALT="Note"></TD
|
||
><TD
|
||
ALIGN="LEFT"
|
||
VALIGN="TOP"
|
||
><P
|
||
>The <TT
|
||
CLASS="OPTION"
|
||
>-exec</TT
|
||
> option to
|
||
<B
|
||
CLASS="COMMAND"
|
||
>find</B
|
||
> should not be confused with the <A
|
||
HREF="internal.html#EXECREF"
|
||
>exec</A
|
||
> shell builtin.</P
|
||
></TD
|
||
></TR
|
||
></TABLE
|
||
></DIV
|
||
><DIV
|
||
CLASS="EXAMPLE"
|
||
><A
|
||
NAME="EX57"
|
||
></A
|
||
><P
|
||
><B
|
||
>Example 16-3. <I
|
||
CLASS="FIRSTTERM"
|
||
>Badname</I
|
||
>, eliminate file names
|
||
in current directory containing bad characters and <A
|
||
HREF="special-chars.html#WHITESPACEREF"
|
||
>whitespace</A
|
||
>.</B
|
||
></P
|
||
><TABLE
|
||
BORDER="0"
|
||
BGCOLOR="#E0E0E0"
|
||
WIDTH="90%"
|
||
><TR
|
||
><TD
|
||
><FONT
|
||
COLOR="#000000"
|
||
><PRE
|
||
CLASS="PROGRAMLISTING"
|
||
>#!/bin/bash
|
||
# badname.sh
|
||
# Delete filenames in current directory containing bad characters.
|
||
|
||
for filename in *
|
||
do
|
||
badname=`echo "$filename" | sed -n /[\+\{\;\"\\\=\?~\(\)\<\>\&\*\|\$]/p`
|
||
# badname=`echo "$filename" | sed -n '/[+{;"\=?~()<>&*|$]/p'` also works.
|
||
# Deletes files containing these nasties: + { ; " \ = ? ~ ( ) < > & * | $
|
||
#
|
||
rm $badname 2>/dev/null
|
||
# ^^^^^^^^^^^ Error messages deep-sixed.
|
||
done
|
||
|
||
# Now, take care of files containing all manner of whitespace.
|
||
find . -name "* *" -exec rm -f {} \;
|
||
# The path name of the file that _find_ finds replaces the "{}".
|
||
# The '\' ensures that the ';' is interpreted literally, as end of command.
|
||
|
||
exit 0
|
||
|
||
#---------------------------------------------------------------------
|
||
# Commands below this line will not execute because of _exit_ command.
|
||
|
||
# An alternative to the above script:
|
||
find . -name '*[+{;"\\=?~()<>&*|$ ]*' -maxdepth 0 \
|
||
-exec rm -f '{}' \;
|
||
# The "-maxdepth 0" option ensures that _find_ will not search
|
||
#+ subdirectories below $PWD.
|
||
|
||
# (Thanks, S.C.)</PRE
|
||
></FONT
|
||
></TD
|
||
></TR
|
||
></TABLE
|
||
></DIV
|
||
><DIV
|
||
CLASS="EXAMPLE"
|
||
><A
|
||
NAME="IDELETE"
|
||
></A
|
||
><P
|
||
><B
|
||
>Example 16-4. Deleting a file by its <I
|
||
CLASS="FIRSTTERM"
|
||
>inode</I
|
||
>
|
||
number</B
|
||
></P
|
||
><TABLE
|
||
BORDER="0"
|
||
BGCOLOR="#E0E0E0"
|
||
WIDTH="90%"
|
||
><TR
|
||
><TD
|
||
><FONT
|
||
COLOR="#000000"
|
||
><PRE
|
||
CLASS="PROGRAMLISTING"
|
||
>#!/bin/bash
|
||
# idelete.sh: Deleting a file by its inode number.
|
||
|
||
# This is useful when a filename starts with an illegal character,
|
||
#+ such as ? or -.
|
||
|
||
ARGCOUNT=1 # Filename arg must be passed to script.
|
||
E_WRONGARGS=70
|
||
E_FILE_NOT_EXIST=71
|
||
E_CHANGED_MIND=72
|
||
|
||
if [ $# -ne "$ARGCOUNT" ]
|
||
then
|
||
echo "Usage: `basename $0` filename"
|
||
exit $E_WRONGARGS
|
||
fi
|
||
|
||
if [ ! -e "$1" ]
|
||
then
|
||
echo "File \""$1"\" does not exist."
|
||
exit $E_FILE_NOT_EXIST
|
||
fi
|
||
|
||
inum=`ls -i | grep "$1" | awk '{print $1}'`
|
||
# inum = inode (index node) number of file
|
||
# -----------------------------------------------------------------------
|
||
# Every file has an inode, a record that holds its physical address info.
|
||
# -----------------------------------------------------------------------
|
||
|
||
echo; echo -n "Are you absolutely sure you want to delete \"$1\" (y/n)? "
|
||
# The '-v' option to 'rm' also asks this.
|
||
read answer
|
||
case "$answer" in
|
||
[nN]) echo "Changed your mind, huh?"
|
||
exit $E_CHANGED_MIND
|
||
;;
|
||
*) echo "Deleting file \"$1\".";;
|
||
esac
|
||
|
||
find . -inum $inum -exec rm {} \;
|
||
# ^^
|
||
# Curly brackets are placeholder
|
||
#+ for text output by "find."
|
||
echo "File "\"$1"\" deleted!"
|
||
|
||
exit 0</PRE
|
||
></FONT
|
||
></TD
|
||
></TR
|
||
></TABLE
|
||
></DIV
|
||
><P
|
||
>The <B
|
||
CLASS="COMMAND"
|
||
>find</B
|
||
> command also works
|
||
without the <TT
|
||
CLASS="OPTION"
|
||
>-exec</TT
|
||
> option.</P
|
||
><P
|
||
> <TABLE
|
||
BORDER="0"
|
||
BGCOLOR="#E0E0E0"
|
||
WIDTH="90%"
|
||
><TR
|
||
><TD
|
||
><FONT
|
||
COLOR="#000000"
|
||
><PRE
|
||
CLASS="PROGRAMLISTING"
|
||
>#!/bin/bash
|
||
# Find suid root files.
|
||
# A strange suid file might indicate a security hole,
|
||
#+ or even a system intrusion.
|
||
|
||
directory="/usr/sbin"
|
||
# Might also try /sbin, /bin, /usr/bin, /usr/local/bin, etc.
|
||
permissions="+4000" # suid root (dangerous!)
|
||
|
||
|
||
for file in $( find "$directory" -perm "$permissions" )
|
||
do
|
||
ls -ltF --author "$file"
|
||
done</PRE
|
||
></FONT
|
||
></TD
|
||
></TR
|
||
></TABLE
|
||
>
|
||
</P
|
||
><P
|
||
>See <A
|
||
HREF="filearchiv.html#EX48"
|
||
>Example 16-30</A
|
||
>, <A
|
||
HREF="special-chars.html#EX58"
|
||
>Example 3-4</A
|
||
>,
|
||
and <A
|
||
HREF="loops1.html#FINDSTRING"
|
||
>Example 11-10</A
|
||
> for scripts using
|
||
<B
|
||
CLASS="COMMAND"
|
||
>find</B
|
||
>. Its <A
|
||
HREF="basic.html#MANREF"
|
||
>manpage</A
|
||
> provides more detail
|
||
on this complex and powerful command.</P
|
||
></DD
|
||
><DT
|
||
><A
|
||
NAME="XARGSREF"
|
||
></A
|
||
><B
|
||
CLASS="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 <A
|
||
HREF="commandsub.html#BACKQUOTESREF"
|
||
>backquotes</A
|
||
>.
|
||
In situations where <A
|
||
HREF="commandsub.html#COMMANDSUBREF"
|
||
>command
|
||
substitution</A
|
||
> fails with a <SPAN
|
||
CLASS="ERRORNAME"
|
||
>too
|
||
many arguments</SPAN
|
||
> error,
|
||
substituting <B
|
||
CLASS="COMMAND"
|
||
>xargs</B
|
||
> often
|
||
works.
|
||
<A
|
||
NAME="AEN10465"
|
||
HREF="#FTN.AEN10465"
|
||
><SPAN
|
||
CLASS="footnote"
|
||
>[1]</SPAN
|
||
></A
|
||
>
|
||
Normally, <B
|
||
CLASS="COMMAND"
|
||
>xargs</B
|
||
> reads from
|
||
<TT
|
||
CLASS="FILENAME"
|
||
>stdin</TT
|
||
> or from a pipe, but it can also
|
||
be given the output of a file.</P
|
||
><P
|
||
>The default command for <B
|
||
CLASS="COMMAND"
|
||
>xargs</B
|
||
> is
|
||
<A
|
||
HREF="internal.html#ECHOREF"
|
||
>echo</A
|
||
>. This means that input
|
||
piped to <B
|
||
CLASS="COMMAND"
|
||
>xargs</B
|
||
> may have linefeeds and
|
||
other whitespace characters stripped out.</P
|
||
><P
|
||
> <TABLE
|
||
BORDER="1"
|
||
BGCOLOR="#E0E0E0"
|
||
WIDTH="90%"
|
||
><TR
|
||
><TD
|
||
><FONT
|
||
COLOR="#000000"
|
||
><PRE
|
||
CLASS="SCREEN"
|
||
><TT
|
||
CLASS="PROMPT"
|
||
>bash$ </TT
|
||
><TT
|
||
CLASS="USERINPUT"
|
||
><B
|
||
>ls -l</B
|
||
></TT
|
||
>
|
||
<TT
|
||
CLASS="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
|
||
>
|
||
|
||
|
||
|
||
<TT
|
||
CLASS="PROMPT"
|
||
>bash$ </TT
|
||
><TT
|
||
CLASS="USERINPUT"
|
||
><B
|
||
>ls -l | xargs</B
|
||
></TT
|
||
>
|
||
<TT
|
||
CLASS="COMPUTEROUTPUT"
|
||
>total 0 -rw-rw-r-- 1 bozo bozo 0 Jan 29 23:58 file1 -rw-rw-r-- 1 bozo bozo 0 Jan...</TT
|
||
>
|
||
|
||
|
||
|
||
<TT
|
||
CLASS="PROMPT"
|
||
>bash$ </TT
|
||
><TT
|
||
CLASS="USERINPUT"
|
||
><B
|
||
>find ~/mail -type f | xargs grep "Linux"</B
|
||
></TT
|
||
>
|
||
<TT
|
||
CLASS="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
|
||
></FONT
|
||
></TD
|
||
></TR
|
||
></TABLE
|
||
>
|
||
</P
|
||
><P
|
||
><TT
|
||
CLASS="USERINPUT"
|
||
><B
|
||
>ls | xargs -p -l gzip</B
|
||
></TT
|
||
> <A
|
||
HREF="filearchiv.html#GZIPREF"
|
||
>gzips</A
|
||
> every file in current
|
||
directory, one at a time, prompting before each
|
||
operation.</P
|
||
><P
|
||
><A
|
||
NAME="XARGSONEATATIME"
|
||
></A
|
||
></P
|
||
><DIV
|
||
CLASS="NOTE"
|
||
><P
|
||
></P
|
||
><TABLE
|
||
CLASS="NOTE"
|
||
WIDTH="90%"
|
||
BORDER="0"
|
||
><TR
|
||
><TD
|
||
WIDTH="25"
|
||
ALIGN="CENTER"
|
||
VALIGN="TOP"
|
||
><IMG
|
||
SRC="../images/note.gif"
|
||
HSPACE="5"
|
||
ALT="Note"></TD
|
||
><TD
|
||
ALIGN="LEFT"
|
||
VALIGN="TOP"
|
||
><P
|
||
>Note that <I
|
||
CLASS="FIRSTTERM"
|
||
>xargs</I
|
||
> processes the
|
||
arguments passed to it sequentially, <EM
|
||
>one at
|
||
a time</EM
|
||
>.</P
|
||
><P
|
||
><TABLE
|
||
BORDER="1"
|
||
BGCOLOR="#E0E0E0"
|
||
WIDTH="90%"
|
||
><TR
|
||
><TD
|
||
><FONT
|
||
COLOR="#000000"
|
||
><PRE
|
||
CLASS="SCREEN"
|
||
><TT
|
||
CLASS="PROMPT"
|
||
>bash$ </TT
|
||
><TT
|
||
CLASS="USERINPUT"
|
||
><B
|
||
>find /usr/bin | xargs file</B
|
||
></TT
|
||
>
|
||
<TT
|
||
CLASS="COMPUTEROUTPUT"
|
||
>/usr/bin: directory
|
||
/usr/bin/foomatic-ppd-options: perl script text executable
|
||
. . .</TT
|
||
>
|
||
</PRE
|
||
></FONT
|
||
></TD
|
||
></TR
|
||
></TABLE
|
||
>
|
||
</P
|
||
></TD
|
||
></TR
|
||
></TABLE
|
||
></DIV
|
||
><P
|
||
><A
|
||
NAME="XARGSLIMARGS"
|
||
></A
|
||
></P
|
||
><DIV
|
||
CLASS="TIP"
|
||
><P
|
||
></P
|
||
><TABLE
|
||
CLASS="TIP"
|
||
WIDTH="90%"
|
||
BORDER="0"
|
||
><TR
|
||
><TD
|
||
WIDTH="25"
|
||
ALIGN="CENTER"
|
||
VALIGN="TOP"
|
||
><IMG
|
||
SRC="../images/tip.gif"
|
||
HSPACE="5"
|
||
ALT="Tip"></TD
|
||
><TD
|
||
ALIGN="LEFT"
|
||
VALIGN="TOP"
|
||
><P
|
||
>An interesting <I
|
||
CLASS="FIRSTTERM"
|
||
>xargs</I
|
||
>
|
||
option is <TT
|
||
CLASS="OPTION"
|
||
>-n <TT
|
||
CLASS="REPLACEABLE"
|
||
><I
|
||
>NN</I
|
||
></TT
|
||
></TT
|
||
>,
|
||
which limits to <TT
|
||
CLASS="REPLACEABLE"
|
||
><I
|
||
>NN</I
|
||
></TT
|
||
> the number
|
||
of arguments passed.</P
|
||
><P
|
||
><TT
|
||
CLASS="USERINPUT"
|
||
><B
|
||
>ls | xargs -n 8 echo</B
|
||
></TT
|
||
> lists the files in the
|
||
current directory in <TT
|
||
CLASS="LITERAL"
|
||
>8</TT
|
||
> columns.</P
|
||
></TD
|
||
></TR
|
||
></TABLE
|
||
></DIV
|
||
><P
|
||
><A
|
||
NAME="XARGSWS"
|
||
></A
|
||
></P
|
||
><DIV
|
||
CLASS="TIP"
|
||
><P
|
||
></P
|
||
><TABLE
|
||
CLASS="TIP"
|
||
WIDTH="90%"
|
||
BORDER="0"
|
||
><TR
|
||
><TD
|
||
WIDTH="25"
|
||
ALIGN="CENTER"
|
||
VALIGN="TOP"
|
||
><IMG
|
||
SRC="../images/tip.gif"
|
||
HSPACE="5"
|
||
ALT="Tip"></TD
|
||
><TD
|
||
ALIGN="LEFT"
|
||
VALIGN="TOP"
|
||
><P
|
||
>Another useful option is
|
||
<TT
|
||
CLASS="OPTION"
|
||
>-0</TT
|
||
>, in combination with <TT
|
||
CLASS="USERINPUT"
|
||
><B
|
||
>find
|
||
-print0</B
|
||
></TT
|
||
> or <TT
|
||
CLASS="USERINPUT"
|
||
><B
|
||
>grep -lZ</B
|
||
></TT
|
||
>. This
|
||
allows handling arguments containing whitespace or
|
||
quotes.</P
|
||
><P
|
||
> <TT
|
||
CLASS="USERINPUT"
|
||
><B
|
||
>find / -type f -print0 | xargs -0 grep -liwZ GUI | xargs -0 rm -f</B
|
||
></TT
|
||
>
|
||
</P
|
||
><P
|
||
> <TT
|
||
CLASS="USERINPUT"
|
||
><B
|
||
>grep -rliwZ GUI / | xargs -0 rm -f</B
|
||
></TT
|
||
>
|
||
</P
|
||
><P
|
||
>Either of the above will remove any file containing <SPAN
|
||
CLASS="QUOTE"
|
||
>"GUI"</SPAN
|
||
>.
|
||
<EM
|
||
>(Thanks, S.C.)</EM
|
||
></P
|
||
><P
|
||
>Or:
|
||
<TABLE
|
||
BORDER="0"
|
||
BGCOLOR="#E0E0E0"
|
||
WIDTH="90%"
|
||
><TR
|
||
><TD
|
||
><FONT
|
||
COLOR="#000000"
|
||
><PRE
|
||
CLASS="PROGRAMLISTING"
|
||
>cat /proc/"$pid"/"$OPTION" | xargs -0 echo
|
||
# Formats output: ^^^^^^^^^^^^^^^
|
||
# From Han Holl's fixup of "get-commandline.sh"
|
||
#+ script in "/dev and /proc" chapter.</PRE
|
||
></FONT
|
||
></TD
|
||
></TR
|
||
></TABLE
|
||
></P
|
||
></TD
|
||
></TR
|
||
></TABLE
|
||
></DIV
|
||
><DIV
|
||
CLASS="TIP"
|
||
><P
|
||
></P
|
||
><TABLE
|
||
CLASS="TIP"
|
||
WIDTH="90%"
|
||
BORDER="0"
|
||
><TR
|
||
><TD
|
||
WIDTH="25"
|
||
ALIGN="CENTER"
|
||
VALIGN="TOP"
|
||
><IMG
|
||
SRC="../images/tip.gif"
|
||
HSPACE="5"
|
||
ALT="Tip"></TD
|
||
><TD
|
||
ALIGN="LEFT"
|
||
VALIGN="TOP"
|
||
><P
|
||
><A
|
||
NAME="XARGSMULTIPROCESS"
|
||
></A
|
||
></P
|
||
><P
|
||
>The <TT
|
||
CLASS="OPTION"
|
||
>-P</TT
|
||
> option to
|
||
<I
|
||
CLASS="FIRSTTERM"
|
||
>xargs</I
|
||
> permits running
|
||
processes in parallel. This speeds up execution
|
||
in a machine with a multicore CPU.</P
|
||
><P
|
||
><TABLE
|
||
BORDER="0"
|
||
BGCOLOR="#E0E0E0"
|
||
WIDTH="90%"
|
||
><TR
|
||
><TD
|
||
><FONT
|
||
COLOR="#000000"
|
||
><PRE
|
||
CLASS="PROGRAMLISTING"
|
||
>#!/bin/bash
|
||
|
||
ls *gif | xargs -t -n1 -P2 gif2png
|
||
# Converts all the gif images in current directory to png.
|
||
|
||
# Options:
|
||
# =======
|
||
# -t Print command to stderr.
|
||
# -n1 At most 1 argument per command line.
|
||
# -P2 Run up to 2 processes simultaneously.
|
||
|
||
# Thank you, Roberto Polli, for the inspiration.</PRE
|
||
></FONT
|
||
></TD
|
||
></TR
|
||
></TABLE
|
||
></P
|
||
></TD
|
||
></TR
|
||
></TABLE
|
||
></DIV
|
||
><DIV
|
||
CLASS="EXAMPLE"
|
||
><A
|
||
NAME="EX41"
|
||
></A
|
||
><P
|
||
><B
|
||
>Example 16-5. Logfile: Using <I
|
||
CLASS="FIRSTTERM"
|
||
>xargs</I
|
||
> to monitor system log</B
|
||
></P
|
||
><TABLE
|
||
BORDER="0"
|
||
BGCOLOR="#E0E0E0"
|
||
WIDTH="90%"
|
||
><TR
|
||
><TD
|
||
><FONT
|
||
COLOR="#000000"
|
||
><PRE
|
||
CLASS="PROGRAMLISTING"
|
||
>#!/bin/bash
|
||
|
||
# Generates a log file in current directory
|
||
# from the tail end of /var/log/messages.
|
||
|
||
# Note: /var/log/messages must be world readable
|
||
# if this script invoked by an ordinary user.
|
||
# #root chmod 644 /var/log/messages
|
||
|
||
LINES=5
|
||
|
||
( date; uname -a ) >>logfile
|
||
# Time and machine name
|
||
echo ---------------------------------------------------------- >>logfile
|
||
tail -n $LINES /var/log/messages | xargs | fmt -s >>logfile
|
||
echo >>logfile
|
||
echo >>logfile
|
||
|
||
exit 0
|
||
|
||
# Note:
|
||
# ----
|
||
# As Frank Wang points out,
|
||
#+ unmatched quotes (either single or double quotes) in the source file
|
||
#+ may give xargs indigestion.
|
||
#
|
||
# He suggests the following substitution for line 15:
|
||
# tail -n $LINES /var/log/messages | tr -d "\"'" | xargs | fmt -s >>logfile
|
||
|
||
|
||
|
||
# Exercise:
|
||
# --------
|
||
# Modify this script to track changes in /var/log/messages at intervals
|
||
#+ of 20 minutes.
|
||
# Hint: Use the "watch" command. </PRE
|
||
></FONT
|
||
></TD
|
||
></TR
|
||
></TABLE
|
||
></DIV
|
||
><P
|
||
><A
|
||
NAME="XARGSCURLYREF"
|
||
></A
|
||
></P
|
||
><P
|
||
><A
|
||
HREF="moreadv.html#CURLYBRACKETSREF"
|
||
>As in
|
||
<B
|
||
CLASS="COMMAND"
|
||
>find</B
|
||
></A
|
||
>, a curly bracket
|
||
pair serves as a placeholder for replacement text.</P
|
||
><DIV
|
||
CLASS="EXAMPLE"
|
||
><A
|
||
NAME="EX42"
|
||
></A
|
||
><P
|
||
><B
|
||
>Example 16-6. Copying files in current directory to another</B
|
||
></P
|
||
><TABLE
|
||
BORDER="0"
|
||
BGCOLOR="#E0E0E0"
|
||
WIDTH="90%"
|
||
><TR
|
||
><TD
|
||
><FONT
|
||
COLOR="#000000"
|
||
><PRE
|
||
CLASS="PROGRAMLISTING"
|
||
>#!/bin/bash
|
||
# copydir.sh
|
||
|
||
# Copy (verbose) all files in current directory ($PWD)
|
||
#+ to directory specified on command-line.
|
||
|
||
E_NOARGS=85
|
||
|
||
if [ -z "$1" ] # Exit if no argument given.
|
||
then
|
||
echo "Usage: `basename $0` directory-to-copy-to"
|
||
exit $E_NOARGS
|
||
fi
|
||
|
||
ls . | xargs -i -t cp ./{} $1
|
||
# ^^ ^^ ^^
|
||
# -t is "verbose" (output command-line to stderr) option.
|
||
# -i is "replace strings" option.
|
||
# {} is a placeholder for output text.
|
||
# This is similar to the use of a curly-bracket pair in "find."
|
||
#
|
||
# List the files in current directory (ls .),
|
||
#+ pass the output of "ls" as arguments to "xargs" (-i -t options),
|
||
#+ then copy (cp) these arguments ({}) to new directory ($1).
|
||
#
|
||
# The net result is the exact equivalent of
|
||
#+ cp * $1
|
||
#+ unless any of the filenames has embedded "whitespace" characters.
|
||
|
||
exit 0</PRE
|
||
></FONT
|
||
></TD
|
||
></TR
|
||
></TABLE
|
||
></DIV
|
||
><DIV
|
||
CLASS="EXAMPLE"
|
||
><A
|
||
NAME="KILLBYNAME"
|
||
></A
|
||
><P
|
||
><B
|
||
>Example 16-7. Killing processes by name</B
|
||
></P
|
||
><TABLE
|
||
BORDER="0"
|
||
BGCOLOR="#E0E0E0"
|
||
WIDTH="90%"
|
||
><TR
|
||
><TD
|
||
><FONT
|
||
COLOR="#000000"
|
||
><PRE
|
||
CLASS="PROGRAMLISTING"
|
||
>#!/bin/bash
|
||
# kill-byname.sh: Killing processes by name.
|
||
# Compare this script with kill-process.sh.
|
||
|
||
# For instance,
|
||
#+ try "./kill-byname.sh xterm" --
|
||
#+ and watch all the xterms on your desktop disappear.
|
||
|
||
# Warning:
|
||
# -------
|
||
# This is a fairly dangerous script.
|
||
# Running it carelessly (especially as root)
|
||
#+ can cause data loss and other undesirable effects.
|
||
|
||
E_BADARGS=66
|
||
|
||
if test -z "$1" # No command-line arg supplied?
|
||
then
|
||
echo "Usage: `basename $0` Process(es)_to_kill"
|
||
exit $E_BADARGS
|
||
fi
|
||
|
||
|
||
PROCESS_NAME="$1"
|
||
ps ax | grep "$PROCESS_NAME" | awk '{print $1}' | xargs -i kill {} 2&>/dev/null
|
||
# ^^ ^^
|
||
|
||
# ---------------------------------------------------------------
|
||
# Notes:
|
||
# -i is the "replace strings" option to xargs.
|
||
# The curly brackets are the placeholder for the replacement.
|
||
# 2&>/dev/null suppresses unwanted error messages.
|
||
#
|
||
# Can grep "$PROCESS_NAME" be replaced by pidof "$PROCESS_NAME"?
|
||
# ---------------------------------------------------------------
|
||
|
||
exit $?
|
||
|
||
# The "killall" command has the same effect as this script,
|
||
#+ but using it is not quite as educational.</PRE
|
||
></FONT
|
||
></TD
|
||
></TR
|
||
></TABLE
|
||
></DIV
|
||
><DIV
|
||
CLASS="EXAMPLE"
|
||
><A
|
||
NAME="WF2"
|
||
></A
|
||
><P
|
||
><B
|
||
>Example 16-8. Word frequency analysis using
|
||
<I
|
||
CLASS="FIRSTTERM"
|
||
>xargs</I
|
||
></B
|
||
></P
|
||
><TABLE
|
||
BORDER="0"
|
||
BGCOLOR="#E0E0E0"
|
||
WIDTH="90%"
|
||
><TR
|
||
><TD
|
||
><FONT
|
||
COLOR="#000000"
|
||
><PRE
|
||
CLASS="PROGRAMLISTING"
|
||
>#!/bin/bash
|
||
# wf2.sh: Crude word frequency analysis on a text file.
|
||
|
||
# Uses 'xargs' to decompose lines of text into single words.
|
||
# Compare this example to the "wf.sh" script later on.
|
||
|
||
|
||
# Check for input file on command-line.
|
||
ARGS=1
|
||
E_BADARGS=85
|
||
E_NOFILE=86
|
||
|
||
if [ $# -ne "$ARGS" ]
|
||
# Correct number of arguments passed to script?
|
||
then
|
||
echo "Usage: `basename $0` filename"
|
||
exit $E_BADARGS
|
||
fi
|
||
|
||
if [ ! -f "$1" ] # Does file exist?
|
||
then
|
||
echo "File \"$1\" does not exist."
|
||
exit $E_NOFILE
|
||
fi
|
||
|
||
|
||
|
||
#####################################################
|
||
cat "$1" | xargs -n1 | \
|
||
# List the file, one word per line.
|
||
tr A-Z a-z | \
|
||
# Shift characters to lowercase.
|
||
sed -e 's/\.//g' -e 's/\,//g' -e 's/ /\
|
||
/g' | \
|
||
# Filter out periods and commas, and
|
||
#+ change space between words to linefeed,
|
||
sort | uniq -c | sort -nr
|
||
# Finally remove duplicates, prefix occurrence count
|
||
#+ and sort numerically.
|
||
#####################################################
|
||
|
||
# This does the same job as the "wf.sh" example,
|
||
#+ but a bit more ponderously, and it runs more slowly (why?).
|
||
|
||
exit $?</PRE
|
||
></FONT
|
||
></TD
|
||
></TR
|
||
></TABLE
|
||
></DIV
|
||
></DD
|
||
><DT
|
||
><A
|
||
NAME="EXPRREF"
|
||
></A
|
||
><TT
|
||
CLASS="USERINPUT"
|
||
><B
|
||
>expr</B
|
||
></TT
|
||
></DT
|
||
><DD
|
||
><P
|
||
>All-purpose expression evaluator:
|
||
Concatenates and evaluates the arguments according
|
||
to the operation given (arguments must be separated
|
||
by spaces). Operations may be arithmetic, comparison,
|
||
string, or logical.</P
|
||
><P
|
||
></P
|
||
><DIV
|
||
CLASS="VARIABLELIST"
|
||
><DL
|
||
><DT
|
||
><TT
|
||
CLASS="USERINPUT"
|
||
><B
|
||
>expr 3 + 5</B
|
||
></TT
|
||
></DT
|
||
><DD
|
||
><P
|
||
>returns <TT
|
||
CLASS="LITERAL"
|
||
>8</TT
|
||
></P
|
||
></DD
|
||
><DT
|
||
><TT
|
||
CLASS="USERINPUT"
|
||
><B
|
||
>expr 5 % 3</B
|
||
></TT
|
||
></DT
|
||
><DD
|
||
><P
|
||
>returns 2</P
|
||
></DD
|
||
><DT
|
||
><TT
|
||
CLASS="USERINPUT"
|
||
><B
|
||
>expr 1 / 0</B
|
||
></TT
|
||
></DT
|
||
><DD
|
||
><P
|
||
>returns the error message, <SPAN
|
||
CLASS="ERRORCODE"
|
||
>expr: division by
|
||
zero</SPAN
|
||
></P
|
||
><P
|
||
>Illegal arithmetic operations not allowed.</P
|
||
></DD
|
||
><DT
|
||
><TT
|
||
CLASS="USERINPUT"
|
||
><B
|
||
>expr 5 \* 3</B
|
||
></TT
|
||
></DT
|
||
><DD
|
||
><P
|
||
>returns 15</P
|
||
><P
|
||
>The multiplication operator
|
||
must be escaped when used in an arithmetic expression
|
||
with <B
|
||
CLASS="COMMAND"
|
||
>expr</B
|
||
>.</P
|
||
></DD
|
||
><DT
|
||
><TT
|
||
CLASS="USERINPUT"
|
||
><B
|
||
>y=`expr $y + 1`</B
|
||
></TT
|
||
></DT
|
||
><DD
|
||
><P
|
||
>Increment a variable, with the same effect
|
||
as <TT
|
||
CLASS="USERINPUT"
|
||
><B
|
||
>let y=y+1</B
|
||
></TT
|
||
> and
|
||
<TT
|
||
CLASS="USERINPUT"
|
||
><B
|
||
>y=$(($y+1))</B
|
||
></TT
|
||
>. This is an
|
||
example of <A
|
||
HREF="arithexp.html#ARITHEXPREF"
|
||
>arithmetic
|
||
expansion</A
|
||
>.</P
|
||
></DD
|
||
><DT
|
||
><A
|
||
NAME="EXPEXTRSUB"
|
||
></A
|
||
><TT
|
||
CLASS="USERINPUT"
|
||
><B
|
||
>z=`expr substr
|
||
$string $position $length`</B
|
||
></TT
|
||
></DT
|
||
><DD
|
||
><P
|
||
>Extract substring of $length characters, starting
|
||
at $position.</P
|
||
></DD
|
||
></DL
|
||
></DIV
|
||
><DIV
|
||
CLASS="EXAMPLE"
|
||
><A
|
||
NAME="EX45"
|
||
></A
|
||
><P
|
||
><B
|
||
>Example 16-9. Using <I
|
||
CLASS="FIRSTTERM"
|
||
>expr</I
|
||
></B
|
||
></P
|
||
><TABLE
|
||
BORDER="0"
|
||
BGCOLOR="#E0E0E0"
|
||
WIDTH="90%"
|
||
><TR
|
||
><TD
|
||
><FONT
|
||
COLOR="#000000"
|
||
><PRE
|
||
CLASS="PROGRAMLISTING"
|
||
>#!/bin/bash
|
||
|
||
# Demonstrating some of the uses of 'expr'
|
||
# =======================================
|
||
|
||
echo
|
||
|
||
# Arithmetic Operators
|
||
# ---------- ---------
|
||
|
||
echo "Arithmetic Operators"
|
||
echo
|
||
a=`expr 5 + 3`
|
||
echo "5 + 3 = $a"
|
||
|
||
a=`expr $a + 1`
|
||
echo
|
||
echo "a + 1 = $a"
|
||
echo "(incrementing a variable)"
|
||
|
||
a=`expr 5 % 3`
|
||
# modulo
|
||
echo
|
||
echo "5 mod 3 = $a"
|
||
|
||
echo
|
||
echo
|
||
|
||
# Logical Operators
|
||
# ------- ---------
|
||
|
||
# Returns 1 if true, 0 if false,
|
||
#+ opposite of normal Bash convention.
|
||
|
||
echo "Logical Operators"
|
||
echo
|
||
|
||
x=24
|
||
y=25
|
||
b=`expr $x = $y` # Test equality.
|
||
echo "b = $b" # 0 ( $x -ne $y )
|
||
echo
|
||
|
||
a=3
|
||
b=`expr $a \> 10`
|
||
echo 'b=`expr $a \> 10`, therefore...'
|
||
echo "If a > 10, b = 0 (false)"
|
||
echo "b = $b" # 0 ( 3 ! -gt 10 )
|
||
echo
|
||
|
||
b=`expr $a \< 10`
|
||
echo "If a < 10, b = 1 (true)"
|
||
echo "b = $b" # 1 ( 3 -lt 10 )
|
||
echo
|
||
# Note escaping of operators.
|
||
|
||
b=`expr $a \<= 3`
|
||
echo "If a <= 3, b = 1 (true)"
|
||
echo "b = $b" # 1 ( 3 -le 3 )
|
||
# There is also a "\>=" operator (greater than or equal to).
|
||
|
||
|
||
echo
|
||
echo
|
||
|
||
|
||
|
||
# String Operators
|
||
# ------ ---------
|
||
|
||
echo "String Operators"
|
||
echo
|
||
|
||
a=1234zipper43231
|
||
echo "The string being operated upon is \"$a\"."
|
||
|
||
# length: length of string
|
||
b=`expr length $a`
|
||
echo "Length of \"$a\" is $b."
|
||
|
||
# index: position of first character in substring
|
||
# that matches a character in string
|
||
b=`expr index $a 23`
|
||
echo "Numerical position of first \"2\" in \"$a\" is \"$b\"."
|
||
|
||
# substr: extract substring, starting position & length specified
|
||
b=`expr substr $a 2 6`
|
||
echo "Substring of \"$a\", starting at position 2,\
|
||
and 6 chars long is \"$b\"."
|
||
|
||
|
||
# The default behavior of the 'match' operations is to
|
||
#+ search for the specified match at the BEGINNING of the string.
|
||
#
|
||
# Using Regular Expressions ...
|
||
b=`expr match "$a" '[0-9]*'` # Numerical count.
|
||
echo Number of digits at the beginning of \"$a\" is $b.
|
||
b=`expr match "$a" '\([0-9]*\)'` # Note that escaped parentheses
|
||
# == == #+ trigger substring match.
|
||
echo "The digits at the beginning of \"$a\" are \"$b\"."
|
||
|
||
echo
|
||
|
||
exit 0</PRE
|
||
></FONT
|
||
></TD
|
||
></TR
|
||
></TABLE
|
||
></DIV
|
||
><DIV
|
||
CLASS="IMPORTANT"
|
||
><P
|
||
></P
|
||
><TABLE
|
||
CLASS="IMPORTANT"
|
||
WIDTH="90%"
|
||
BORDER="0"
|
||
><TR
|
||
><TD
|
||
WIDTH="25"
|
||
ALIGN="CENTER"
|
||
VALIGN="TOP"
|
||
><IMG
|
||
SRC="../images/important.gif"
|
||
HSPACE="5"
|
||
ALT="Important"></TD
|
||
><TD
|
||
ALIGN="LEFT"
|
||
VALIGN="TOP"
|
||
><P
|
||
>The <A
|
||
HREF="special-chars.html#NULLREF"
|
||
>:
|
||
(<I
|
||
CLASS="FIRSTTERM"
|
||
>null</I
|
||
>)</A
|
||
> operator
|
||
can substitute for <B
|
||
CLASS="COMMAND"
|
||
>match</B
|
||
>. For example,
|
||
<TT
|
||
CLASS="USERINPUT"
|
||
><B
|
||
>b=`expr $a : [0-9]*`</B
|
||
></TT
|
||
> is the
|
||
exact equivalent of <TT
|
||
CLASS="USERINPUT"
|
||
><B
|
||
>b=`expr match $a
|
||
[0-9]*`</B
|
||
></TT
|
||
> in the above listing.</P
|
||
><P
|
||
><TABLE
|
||
BORDER="0"
|
||
BGCOLOR="#E0E0E0"
|
||
WIDTH="90%"
|
||
><TR
|
||
><TD
|
||
><FONT
|
||
COLOR="#000000"
|
||
><PRE
|
||
CLASS="PROGRAMLISTING"
|
||
>#!/bin/bash
|
||
|
||
echo
|
||
echo "String operations using \"expr \$string : \" construct"
|
||
echo "==================================================="
|
||
echo
|
||
|
||
a=1234zipper5FLIPPER43231
|
||
|
||
echo "The string being operated upon is \"`expr "$a" : '\(.*\)'`\"."
|
||
# Escaped parentheses grouping operator. == ==
|
||
|
||
# ***************************
|
||
#+ Escaped parentheses
|
||
#+ match a substring
|
||
# ***************************
|
||
|
||
|
||
# If no escaped parentheses ...
|
||
#+ then 'expr' converts the string operand to an integer.
|
||
|
||
echo "Length of \"$a\" is `expr "$a" : '.*'`." # Length of string
|
||
|
||
echo "Number of digits at the beginning of \"$a\" is `expr "$a" : '[0-9]*'`."
|
||
|
||
# ------------------------------------------------------------------------- #
|
||
|
||
echo
|
||
|
||
echo "The digits at the beginning of \"$a\" are `expr "$a" : '\([0-9]*\)'`."
|
||
# == ==
|
||
echo "The first 7 characters of \"$a\" are `expr "$a" : '\(.......\)'`."
|
||
# ===== == ==
|
||
# Again, escaped parentheses force a substring match.
|
||
#
|
||
echo "The last 7 characters of \"$a\" are `expr "$a" : '.*\(.......\)'`."
|
||
# ==== end of string operator ^^
|
||
# (In fact, means skip over one or more of any characters until specified
|
||
#+ substring found.)
|
||
|
||
echo
|
||
|
||
exit 0</PRE
|
||
></FONT
|
||
></TD
|
||
></TR
|
||
></TABLE
|
||
></P
|
||
></TD
|
||
></TR
|
||
></TABLE
|
||
></DIV
|
||
></DD
|
||
></DL
|
||
></DIV
|
||
><P
|
||
>The above script illustrates how
|
||
<B
|
||
CLASS="COMMAND"
|
||
>expr</B
|
||
> uses the <I
|
||
CLASS="FIRSTTERM"
|
||
>escaped
|
||
parentheses -- \( ... \) --</I
|
||
> grouping operator
|
||
in tandem with <A
|
||
HREF="regexp.html#REGEXREF"
|
||
>regular
|
||
expression</A
|
||
> parsing to match a substring.
|
||
Here is a another example, this time from <SPAN
|
||
CLASS="QUOTE"
|
||
>"real
|
||
life."</SPAN
|
||
>
|
||
|
||
<TABLE
|
||
BORDER="0"
|
||
BGCOLOR="#E0E0E0"
|
||
WIDTH="100%"
|
||
><TR
|
||
><TD
|
||
><FONT
|
||
COLOR="#000000"
|
||
><PRE
|
||
CLASS="PROGRAMLISTING"
|
||
># Strip the whitespace from the beginning and end.
|
||
LRFDATE=`expr "$LRFDATE" : '[[:space:]]*\(.*\)[[:space:]]*$'`
|
||
|
||
# From Peter Knowles' "booklistgen.sh" script
|
||
#+ for converting files to Sony Librie/PRS-50X format.
|
||
# (http://booklistgensh.peterknowles.com)</PRE
|
||
></FONT
|
||
></TD
|
||
></TR
|
||
></TABLE
|
||
>
|
||
|
||
</P
|
||
><P
|
||
><A
|
||
HREF="wrapper.html#PERLREF"
|
||
>Perl</A
|
||
>,
|
||
<A
|
||
HREF="sedawk.html#SEDREF"
|
||
>sed</A
|
||
>, and <A
|
||
HREF="awk.html#AWKREF"
|
||
>awk</A
|
||
> have far superior string
|
||
parsing facilities. A short <B
|
||
CLASS="COMMAND"
|
||
>sed</B
|
||
> or
|
||
<B
|
||
CLASS="COMMAND"
|
||
>awk</B
|
||
> <SPAN
|
||
CLASS="QUOTE"
|
||
>"subroutine"</SPAN
|
||
> within
|
||
a script (see <A
|
||
HREF="wrapper.html"
|
||
>Section 36.2</A
|
||
>) is an attractive
|
||
alternative to <B
|
||
CLASS="COMMAND"
|
||
>expr</B
|
||
>.</P
|
||
><P
|
||
>See <A
|
||
HREF="string-manipulation.html"
|
||
>Section 10.1</A
|
||
> for more on
|
||
using <B
|
||
CLASS="COMMAND"
|
||
>expr</B
|
||
> in string operations.</P
|
||
></DIV
|
||
><H3
|
||
CLASS="FOOTNOTES"
|
||
>Notes</H3
|
||
><TABLE
|
||
BORDER="0"
|
||
CLASS="FOOTNOTES"
|
||
WIDTH="100%"
|
||
><TR
|
||
><TD
|
||
ALIGN="LEFT"
|
||
VALIGN="TOP"
|
||
WIDTH="5%"
|
||
><A
|
||
NAME="FTN.AEN10465"
|
||
HREF="moreadv.html#AEN10465"
|
||
><SPAN
|
||
CLASS="footnote"
|
||
>[1]</SPAN
|
||
></A
|
||
></TD
|
||
><TD
|
||
ALIGN="LEFT"
|
||
VALIGN="TOP"
|
||
WIDTH="95%"
|
||
><P
|
||
>And even when <I
|
||
CLASS="FIRSTTERM"
|
||
>xargs</I
|
||
> is
|
||
not strictly necessary, it can speed up execution of a command
|
||
involving <A
|
||
HREF="timedate.html#BATCHPROCREF"
|
||
>batch-processing</A
|
||
> of multiple
|
||
files.</P
|
||
></TD
|
||
></TR
|
||
></TABLE
|
||
><DIV
|
||
CLASS="NAVFOOTER"
|
||
><HR
|
||
ALIGN="LEFT"
|
||
WIDTH="100%"><TABLE
|
||
SUMMARY="Footer navigation table"
|
||
WIDTH="100%"
|
||
BORDER="0"
|
||
CELLPADDING="0"
|
||
CELLSPACING="0"
|
||
><TR
|
||
><TD
|
||
WIDTH="33%"
|
||
ALIGN="left"
|
||
VALIGN="top"
|
||
><A
|
||
HREF="basic.html"
|
||
ACCESSKEY="P"
|
||
>Prev</A
|
||
></TD
|
||
><TD
|
||
WIDTH="34%"
|
||
ALIGN="center"
|
||
VALIGN="top"
|
||
><A
|
||
HREF="index.html"
|
||
ACCESSKEY="H"
|
||
>Home</A
|
||
></TD
|
||
><TD
|
||
WIDTH="33%"
|
||
ALIGN="right"
|
||
VALIGN="top"
|
||
><A
|
||
HREF="timedate.html"
|
||
ACCESSKEY="N"
|
||
>Next</A
|
||
></TD
|
||
></TR
|
||
><TR
|
||
><TD
|
||
WIDTH="33%"
|
||
ALIGN="left"
|
||
VALIGN="top"
|
||
>Basic Commands</TD
|
||
><TD
|
||
WIDTH="34%"
|
||
ALIGN="center"
|
||
VALIGN="top"
|
||
><A
|
||
HREF="external.html"
|
||
ACCESSKEY="U"
|
||
>Up</A
|
||
></TD
|
||
><TD
|
||
WIDTH="33%"
|
||
ALIGN="right"
|
||
VALIGN="top"
|
||
>Time / Date Commands</TD
|
||
></TR
|
||
></TABLE
|
||
></DIV
|
||
></BODY
|
||
></HTML
|
||
> |