384 lines
6.4 KiB
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"
|
|
> #!/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
|
|
> </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"
|
|
> #!/bin/bash
|
|
if [ $# -lt 1 ]; then
|
|
echo "Usage: $0 package(s)"
|
|
exit 1
|
|
fi
|
|
while (($#)); do
|
|
yum install "$1" << 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
|
|
> |