old-www/LDP/Bash-Beginners-Guide/html/sect_09_07.html

384 lines
6.4 KiB
HTML

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML
><HEAD
><TITLE
>The shift built-in</TITLE
><META
NAME="GENERATOR"
CONTENT="Modular DocBook HTML Stylesheet Version 1.7"><LINK
REL="HOME"
TITLE="Bash Guide for Beginners"
HREF="index.html"><LINK
REL="UP"
TITLE="Repetitive tasks"
HREF="chap_09.html"><LINK
REL="PREVIOUS"
TITLE="Making menus with the select built-in"
HREF="sect_09_06.html"><LINK
REL="NEXT"
TITLE="Summary"
HREF="sect_09_08.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"
>Bash Guide for Beginners</TH
></TR
><TR
><TD
WIDTH="10%"
ALIGN="left"
VALIGN="bottom"
><A
HREF="sect_09_06.html"
ACCESSKEY="P"
>Prev</A
></TD
><TD
WIDTH="80%"
ALIGN="center"
VALIGN="bottom"
>Chapter 9. Repetitive tasks</TD
><TD
WIDTH="10%"
ALIGN="right"
VALIGN="bottom"
><A
HREF="sect_09_08.html"
ACCESSKEY="N"
>Next</A
></TD
></TR
></TABLE
><HR
ALIGN="LEFT"
WIDTH="100%"></DIV
><DIV
CLASS="sect1"
><H1
CLASS="sect1"
><A
NAME="sect_09_07"
></A
>9.7. The shift built-in</H1
><DIV
CLASS="sect2"
><H2
CLASS="sect2"
><A
NAME="sect_09_07_01"
></A
>9.7.1. What does it do?</H2
><P
>The <B
CLASS="command"
>shift</B
> command is one of the Bourne shell built-ins that comes with Bash. This command takes one argument, a number. The positional parameters are shifted to the left by this number, <EM
>N</EM
>. The positional parameters from <TT
CLASS="varname"
>N+1</TT
> to <TT
CLASS="varname"
>$#</TT
> are renamed to variable names from <TT
CLASS="varname"
>$1</TT
> to <TT
CLASS="varname"
>$# - N+1</TT
>.</P
><P
>Say you have a command that takes 10 arguments, and N is 4, then <TT
CLASS="varname"
>$4</TT
> becomes <TT
CLASS="varname"
>$1</TT
>, <TT
CLASS="varname"
>$5</TT
> becomes <TT
CLASS="varname"
>$2</TT
> and so on. <TT
CLASS="varname"
>$10</TT
> becomes <TT
CLASS="varname"
>$7</TT
> and the original <TT
CLASS="varname"
>$1</TT
>, <TT
CLASS="varname"
>$2</TT
> and <TT
CLASS="varname"
>$3</TT
> are thrown away.</P
><P
>If N is zero or greater than <TT
CLASS="varname"
>$#</TT
>, the positional parameters are not changed (the total number of arguments, see <A
HREF="sect_07_02.html#sect_07_02_01_02"
>Section 7.2.1.2</A
>) and the command has no effect. If N is not present, it is assumed to be 1. The return status is zero unless N is greater than <TT
CLASS="varname"
>$#</TT
> or less than zero; otherwise it is non-zero.</P
></DIV
><DIV
CLASS="sect2"
><H2
CLASS="sect2"
><A
NAME="sect_09_07_02"
></A
>9.7.2. Examples</H2
><P
>A shift statement is typically used when the number of arguments to a command is not known in advance, for instance when users can give as many arguments as they like. In such cases, the arguments are usually processed in a <B
CLASS="command"
>while</B
> loop with a test condition of <B
CLASS="command"
>(( $# ))</B
>. This condition is true as long as the number of arguments is greater than zero. The <TT
CLASS="varname"
>$1</TT
> variable and the <B
CLASS="command"
>shift</B
> statement process each argument. The number of arguments is reduced each time <B
CLASS="command"
>shift</B
> is executed and eventually becomes zero, upon which the <B
CLASS="command"
>while</B
> loop exits.</P
><P
>The example below, <TT
CLASS="filename"
>cleanup.sh</TT
>, uses <B
CLASS="command"
>shift</B
> statements to process each file in the list generated by <B
CLASS="command"
>find</B
>:</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="screen"
>&#13;#!/bin/bash
# This script can clean up files that were last accessed over 365 days ago.
USAGE="Usage: $0 dir1 dir2 dir3 ... dirN"
if [ "$#" == "0" ]; then
echo "$USAGE"
exit 1
fi
while (( "$#" )); do
if [[ $(ls "$1") == "" ]]; then
echo "Empty directory, nothing to be done."
else
find "$1" -type f -a -atime +365 -exec rm -i {} \;
fi
shift
done
</PRE
></FONT
></TD
></TR
></TABLE
><DIV
CLASS="note"
><P
></P
><TABLE
CLASS="note"
WIDTH="100%"
BORDER="0"
><TR
><TD
WIDTH="25"
ALIGN="CENTER"
VALIGN="TOP"
><IMG
SRC="../images/note.gif"
HSPACE="5"
ALT="Note"></TD
><TH
ALIGN="LEFT"
VALIGN="CENTER"
><B
>-exec vs. xargs</B
></TH
></TR
><TR
><TD
>&nbsp;</TD
><TD
ALIGN="LEFT"
VALIGN="TOP"
><P
>The above <B
CLASS="command"
>find</B
> command can be replaced with the following:</P
><P
><B
CLASS="command"
>find <TT
CLASS="option"
>options</TT
> | xargs [commands_to_execute_on_found_files]</B
> </P
><P
>The <B
CLASS="command"
>xargs</B
> command builds and executes command lines from standard input. This has the advantage that the command line is filled until the system limit is reached. Only then will the command to execute be called, in the above example this would be <B
CLASS="command"
>rm</B
>. If there are more arguments, a new command line will be used, until that one is full or until there are no more arguments. The same thing using <B
CLASS="command"
>find <TT
CLASS="option"
>-exec</TT
></B
> calls on the command to execute on the found files every time a file is found. Thus, using <B
CLASS="command"
>xargs</B
> greatly speeds up your scripts and the performance of your machine.</P
></TD
></TR
></TABLE
></DIV
><P
>In the next example, we modified the script from <A
HREF="sect_08_02.html#sect_08_02_04_04"
>Section 8.2.4.4</A
> so that it accepts multiple packages to install at once:</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="screen"
>&#13;#!/bin/bash
if [ $# -lt 1 ]; then
echo "Usage: $0 package(s)"
exit 1
fi
while (($#)); do
yum install "$1" &#60;&#60; CONFIRM
y
CONFIRM
shift
done
</PRE
></FONT
></TD
></TR
></TABLE
></DIV
></DIV
><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="sect_09_06.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="sect_09_08.html"
ACCESSKEY="N"
>Next</A
></TD
></TR
><TR
><TD
WIDTH="33%"
ALIGN="left"
VALIGN="top"
>Making menus with the select built-in</TD
><TD
WIDTH="34%"
ALIGN="center"
VALIGN="top"
><A
HREF="chap_09.html"
ACCESSKEY="U"
>Up</A
></TD
><TD
WIDTH="33%"
ALIGN="right"
VALIGN="top"
>Summary</TD
></TR
></TABLE
></DIV
></BODY
></HTML
>