Unix - Shell Programming

Shell Programming

Introduction to Shell Programs
  • Unix provides a vast array of commands, but inevitably, there will be tasks for which no existing command is perfectly suited.

  • In such scenarios, users can build their own solutions by writing shell programs (also known as shell scripts).

  • The shell itself functions as a programming language.

  • A shell program is fundamentally a sequential list of Unix commands that are executed in the specified order, akin to a batch file or a list of programs to run.

Comments
  • Comments in a shell script begin with the # symbol.

  • Example:
    bash # This is a comment

  • Comments are ignored by the shell interpreter; their sole purpose is to improve human readability and understanding of the code.

  • It is good practice to use comments to explain the logic and purpose of different parts of your script.

Shell Executables and Execution Methods
  • Basic Structure of a Shell Script: A typical shell script starts with a "shebang" line, which specifies the interpreter to use for running the script.

    • Example Script (testScript.sh):
      bash #!/bin/bash echo "hello world!" exit 0

    • When executed, this script would print "hello world!" to the console.

  • Methods for Running Shell Executables:

    1. source FILENAME: Runs the script in the current shell environment.

    2. /bin/bash FILENAME (or sh FILENAME): Explicitly invokes the specified shell interpreter to run the script.

    3. Making the file executable:

      • Change file permissions: chmod +x FILENAME

      • Then, run it directly: ./FILENAME (if in current directory) or /path/to/FILENAME.

      • Shebang Line: The first line of the script, #!/bin/bash (or #!/usr/bin/perl for Perl scripts, etc.), tells the operating system which interpreter should be used when the script is executed directly.

Return Values and Exit Codes
  • Every program and shell command returns an integer value upon completion.

  • This return value (or exit code) communicates the success or failure of the program to other programs or to the shell.

  • A return value of 00 typically signifies successful execution or a True condition.

  • A return value of 11 (or any other non-zero integer) generally indicates failure or a False condition.

Variable Discussion

Definition and Naming Conventions
  • Shell variables are used to store values within a script.

  • Naming Rules:

    • Can consist of any combination of letters, numbers, and the underscore (_) symbol.

    • Must begin with a letter or an underscore.

    • Are case-sensitive (e.g., D and d are considered two distinct variables).

Setting and Accessing Variables
  • Setting Variables: Assignment is done using the == operator.

    • No prior declaration of variable type is necessary; all variables are treated as strings of characters by default.

    • Example: d=date (assigns the string date to variable d).

  • Accessing Variables: Values are retrieved by prefixing the variable name with a symbol.

    • The shell performs variable substitution, replacing the variable name with its stored value.

    • Examples:

      • echo $d

      • echo ${d}

The Difference Between and { } for Variables
  • Using $VAR is often sufficient, but VAR can cause ambiguity if the variable name is immediately followed by characters that could be part of a longer variable name.

  • Example Scenario: If you want to print "blueSky" and have Color=blue.

    • echo "$ColorSky": The shell will attempt to find a variable named ColorSky, which likely doesn't exist, resulting in an empty output.

    • echo "${Color}Sky": The curly braces { } explicitly delineate the variable name (Color), ensuring that Sky is treated as a separate literal string appended to the variable's value.

      • This would correctly output "blueSky".

Variable Usage Examples
  • d=date

    • echo $d -> date (prints the string "date")

    • echo ${d}: -> date: (prints the string "date" followed by a colon)

    • $d -> Executing date as a command (since d holds the string date, which is a recognized command), outputs system date/time (e.g., Thu Feb 10 07:43:51 PST 2005).

    • ${d} -> Also executes date as a command, outputs system date/time (e.g., Thu Feb 10 07:44:02 PST 2005).

    • Note: If a variable contains a command name, using VAR or ${VAR} without quotes will execute that command.

Reading User Input into Variables
  • Usage: read var1 var2 ...

  • The read command reads values from standard input (typically the keyboard) and assigns them sequentially to the specified variables.

  • Behavior with multiple words/variables:

    • If more words are typed by the user than there are variables, the excess words are all assigned to the last variable.

    • If more variables are specified than words provided by the user, the excess variables remain empty.

  • Examples:

    • read var, then user types hello -> echo $var outputs hello.

    • read var var2, then user types hello world -> echo $var $var2 outputs hello world.

    • read var, then user types hello again world -> echo $var outputs hello again world (entire line goes to var).

    • read var var2, then user types hello -> echo $var2 outputs an empty line (because var2 received no input).

Single, Double, and Backtick Quotes
  • Single Quotes (''): Do not interpret any variables, commands, or special characters. The text within single quotes is treated as a literal string.

    • Example: echo '$d' outputs $d.

  • Double Quotes (""): Interpret variables (VAR</code>),commandsubstitutions(<code></code>), command substitutions (<code> ext{(command)}), and some escape sequences, but prevent word splitting and pathname expansion.

    • Example: echo "$d" outputs date (if d=date).

  • Backticks (`): Treat the enclosed content as a command to be executed. The output of that command is then substituted into the current command.

    • Example: If d=date, then echo exttt{ extasciigrave}date exttt{ extasciigrave} executes the date command and outputs its result (e.g., Thu Feb 10 07:21:07 PST 2005). This is a form of command substitution.

Command Line Parameters

Accessing Command Line Inputs
  • Just like other Unix programs, shell scripts can receive parameters directly from the command line when they are executed.

  • This differs from user input (using read), as command-line parameters are known before the script begins execution, not typed in during execution.

  • Example: If you run testScript.sh testFile, testFile is a command-line parameter.

Special Variables for Command Line Parameters
  • The shell provides special built-in variables to access command-line arguments:

    • 0</code>:Representsthenameoftherunningscriptitself.</p></li><li><p><code></code>: Represents the name of the running script itself.</p></li><li><p><code>1</code><code></code> - <code>9</code>:Representthefirstthroughninthargumentspassedtothescript.</p></li><li><p><code></code>: Represent the first through ninth arguments passed to the script.</p></li><li><p><code>*</code>:Representsallcommandlineargumentsasasinglestring.</p></li><li><p><code></code>: Represents all command-line arguments as a single string.</p></li><li><p><code>#</code>:Representsthetotalnumberofcommandlineargumentspassedtothescript(excluding<code></code>: Represents the total number of command-line arguments passed to the script (excluding <code>0).

Example of Command Line Parameters
  • Script (testScript.sh):
    bash #!/bin/bash echo "The name of the program is: $0" echo "The first parameter is: $1" echo "There are $# parameters" echo "All of the parameters are: $*" exit 0

  • Execution: testScript.sh par1 par2 par3 par4

  • Output:
    text The name of the program is: /testScript.sh The first parameter is: par1 There are 4 parameters All of the parameters are: par1 par2 par3 par4

Arithmetic Discussion

Basic Arithmetic Operations
  • Variables containing numeric values can be treated arithmetically (added, subtracted, etc.).

The (( )) Command for Arithmetic
  • Usage: result=$(( EXPRESSION )) evaluates the EXPRESSION and substitutes its numerical result.

    • Parentheses can also be used explicitly (( EXPRESSION )) in contexts like if statements or for simple evaluation without outputting results.

  • Supported Operators:

    • +</code>:Addition</p></li><li><p><code></code>: Addition</p></li><li><p><code>-</code>:Subtraction</p></li><li><p><code></code>: Subtraction</p></li><li><p><code>*</code>:Multiplication</p></li><li><p><code></code>: Multiplication</p></li><li><p><code>/</code>:Division</p></li><li><p><code></code>: Division</p></li><li><p><code>%: Modulo (remainder)

  • Examples:

    • echo $(( 1 + 6 )) outputs 7.

    • echo $(( 2 * 3 )) outputs 6.

    • echo $(( 4 % 3 )) outputs 1.

Other Arithmetic Options
  • ( ) </code>:Usedforgroupingexpressions,influencingorderofoperations.</p></li><li><p><code></code>: Used for grouping expressions, influencing order of operations.</p></li><li><p><code>|</code>:Bitwise/logicalOR(check<code>man</code>pageforfulldetails).</p></li><li><p><code></code>: Bitwise/logical OR (check <code>man</code> page for full details).</p></li><li><p><code>&</code>:Bitwise/logicalAND(check<code>man</code>pageforfulldetails).</p></li><li><p>Manyotheroperatorsareavailable;consulttheshells<code>man</code>page(e.g.,<code>manbash</code>)foracomprehensivelist.</p></li></ul><h4id="31e3caa8d6294574a9081607f424db64"datatocid="31e3caa8d6294574a9081607f424db64"collapsed="false"seolevelmigrated="true">ControlFlowStatements</h4><h5id="abdaa56c015e466ea5101398c21d3b91"datatocid="abdaa56c015e466ea5101398c21d3b91"collapsed="false"seolevelmigrated="true">Overview</h5><ul><li><p>Shellscriptscanbemoresophisticatedthanjustalinearlistofcommands.</p></li><li><p><strong>Controlflowstatements</strong>allowscriptstomakedecisionsandrepeatactionsbasedonconditions.</p></li><li><p><strong>ExampleUseCase:</strong>Printingafileonlyifitisnotabinaryfile.</p></li></ul><h5id="96ee9559baea4f82b522b67b19637385"datatocid="96ee9559baea4f82b522b67b19637385"collapsed="false"seolevelmigrated="true">The<code>test</code>Command</h5><ul><li><p><strong>Purpose:</strong>Usedtocheckifspecificconditionsaretrue.</p></li><li><p><strong>Usage:</strong><code>testEXPRESSION</code></p></li></ul><h5id="0f9646a1e35a4c23bef2507704917440"datatocid="0f9646a1e35a4c23bef2507704917440"collapsed="false"seolevelmigrated="true"><code>test</code>CommandConditions:Comparisons</h5><ul><li><p><strong>NumericComparisons</strong>(forintegers):</p><ul><li><p><code>eq</code>:Equalto(<code></code>: Bitwise/logical AND (check <code>man</code> page for full details).</p></li><li><p>Many other operators are available; consult the shell's <code>man</code> page (e.g., <code>man bash</code>) for a comprehensive list.</p></li></ul><h4 id="31e3caa8-d629-4574-a908-1607f424db64" data-toc-id="31e3caa8-d629-4574-a908-1607f424db64" collapsed="false" seolevelmigrated="true">Control Flow Statements</h4><h5 id="abdaa56c-015e-466e-a510-1398c21d3b91" data-toc-id="abdaa56c-015e-466e-a510-1398c21d3b91" collapsed="false" seolevelmigrated="true">Overview</h5><ul><li><p>Shell scripts can be more sophisticated than just a linear list of commands.</p></li><li><p><strong>Control flow statements</strong> allow scripts to make decisions and repeat actions based on conditions.</p></li><li><p><strong>Example Use Case:</strong> Printing a file only if it is not a binary file.</p></li></ul><h5 id="96ee9559-baea-4f82-b522-b67b19637385" data-toc-id="96ee9559-baea-4f82-b522-b67b19637385" collapsed="false" seolevelmigrated="true">The <code>test</code> Command</h5><ul><li><p><strong>Purpose:</strong> Used to check if specific conditions are true.</p></li><li><p><strong>Usage:</strong> <code>test EXPRESSION</code></p></li></ul><h5 id="0f9646a1-e35a-4c23-bef2-507704917440" data-toc-id="0f9646a1-e35a-4c23-bef2-507704917440" collapsed="false" seolevelmigrated="true"><code>test</code> Command Conditions: Comparisons</h5><ul><li><p><strong>Numeric Comparisons</strong> (for integers):</p><ul><li><p><code>-eq</code>: Equal to (<code>=) (e.g., test $VAR1 -eq $VAR2)

  • -ne: Not equal to ( ext{!}=) (e.g., test $VAR1 -ne $VAR2)

  • -lt: Less than (<) (e.g., test $VAR1 -lt $VAR2)

  • -le: Less than or equal to ( ext{<=}) (e.g., test $VAR1 -le $VAR2)

  • -gt: Greater than (>) (e.g., test $VAR1 -gt $VAR2)

  • -ge: Greater than or equal to ( ext{>=}) (e.g., test $VAR1 -ge $VAR2)

test Command Conditions: System/File Checks
  • -d FILE: True if FILE exists and is a directory.

  • -e FILE: True if FILE exists.

  • -f FILE: True if FILE exists and is a regular file (not a directory or special file).

  • -s FILE: True if FILE exists and its size is greater than zero (i.e., non-empty).

  • -x FILE: True if FILE exists and is executable.

test Command Conditions: Logical Operators
  • ! EXPRESSION: Logical NOT. Negates the result of the following check.

    • Example: test ! -x tFile (True if tFile is not executable).

  • EXPRESSION1 -a EXPRESSION2: Logical AND. True if both EXPRESSION1 and EXPRESSION2 are true.

    • Example: test $1 -eq $2 -a $2 -gt 5 (True if first arg equals second arg AND second arg is greater than 5).

  • EXPRESSION1 -o EXPRESSION2: Logical OR. True if EXPRESSION1 is true OR EXPRESSION2 is true.

    • Example: test $1 -eq $2 -o $2 -gt 5 (True if first arg equals second arg OR second arg is greater than 5</code>).</p></li></ul></li></ul><h5id="05d59d19d2d54e0ba3cdad078da53964"datatocid="05d59d19d2d54e0ba3cdad078da53964"collapsed="false"seolevelmigrated="true">Shortcutfor<code>test</code>:SquareBrackets<code>[]</code></h5><ul><li><p>The<code>test</code>commandisveryfrequentlyused,soaconciseshortcut<code>[]</code>exists.</p></li><li><p><strong>Usage:</strong><code>[EXPRESSION]</code>.Crucially,theremustbespacesaroundthebracketsandtheexpression.</p></li><li><p><strong>Example:</strong><code>[ftFile]</code>isequivalentto<code>testftFile</code>.</p></li></ul><h5id="20d28dc83fa043bdaf8cfefe9fa6f8ec"datatocid="20d28dc83fa043bdaf8cfefe9fa6f8ec"collapsed="false"seolevelmigrated="true">Applicationof<code>test</code>and<code>[]</code></h5><ul><li><p>Thesecommandsarefundamentalforcontrollingtheflowofascript.</p></li><li><p>Theresultofa<code>test</code>or<code>[]</code>condition(success/failure,representedbytheexitcode)guidessubsequentexecution.</p></li><li><p>Theyareprimarilyutilizedwithinconditionalstatementslike<code>if</code>.</p></li></ul><h5id="0f600d5e79b34bf897a34b3073eb7c60"datatocid="0f600d5e79b34bf897a34b3073eb7c60"collapsed="false"seolevelmigrated="true">ConditionalStatements</h5><h6id="ea6ff89218354782a40076e92139c77c"datatocid="ea6ff89218354782a40076e92139c77c"collapsed="false"seolevelmigrated="true"><code>ifthenfi</code></h6><ul><li><p><strong>Purpose:</strong>Executesablockof<code>STATEMENTS</code>onlyifa<code>CONDITION</code>istrue.</p></li><li><p><strong>Syntax:</strong><br><code>bashif[CONDITION];thenSTATEMENTSfi</code></p></li><li><p><strong>Flowchart:</strong>Condition</code>).</p></li></ul></li></ul><h5 id="05d59d19-d2d5-4e0b-a3cd-ad078da53964" data-toc-id="05d59d19-d2d5-4e0b-a3cd-ad078da53964" collapsed="false" seolevelmigrated="true">Shortcut for <code>test</code>: Square Brackets <code>[ ]</code></h5><ul><li><p>The <code>test</code> command is very frequently used, so a concise shortcut <code>[ ]</code> exists.</p></li><li><p><strong>Usage:</strong> <code>[ EXPRESSION ]</code>. Crucially, there must be spaces around the brackets and the expression.</p></li><li><p><strong>Example:</strong> <code>[ -f tFile ]</code> is equivalent to <code>test -f tFile</code>.</p></li></ul><h5 id="20d28dc8-3fa0-43bd-af8c-fefe9fa6f8ec" data-toc-id="20d28dc8-3fa0-43bd-af8c-fefe9fa6f8ec" collapsed="false" seolevelmigrated="true">Application of <code>test</code> and <code>[ ]</code></h5><ul><li><p>These commands are fundamental for controlling the flow of a script.</p></li><li><p>The result of a <code>test</code> or <code>[ ]</code> condition (success/failure, represented by the exit code) guides subsequent execution.</p></li><li><p>They are primarily utilized within conditional statements like <code>if</code>.</p></li></ul><h5 id="0f600d5e-79b3-4bf8-97a3-4b3073eb7c60" data-toc-id="0f600d5e-79b3-4bf8-97a3-4b3073eb7c60" collapsed="false" seolevelmigrated="true">Conditional Statements</h5><h6 id="ea6ff892-1835-4782-a400-76e92139c77c" data-toc-id="ea6ff892-1835-4782-a400-76e92139c77c" collapsed="false" seolevelmigrated="true"><code>if then fi</code></h6><ul><li><p><strong>Purpose:</strong> Executes a block of <code>STATEMENTS</code> only if a <code>CONDITION</code> is true.</p></li><li><p><strong>Syntax:</strong><br><code>bash if [ CONDITION ]; then STATEMENTS fi</code></p></li><li><p><strong>Flowchart:</strong> Condition\rightarrowYesYes\rightarrowStatementsStatements\rightarrowEnd<code>if</code><br>ConditionEnd <code>if</code><br>Condition\rightarrowNoNo\rightarrow End if

    • Example Script (safeCat.sh):bash #!/bin/bash if [ -x "$1" ]; then cat "$1" fi

      • Running safeCat.sh regularFile (assuming regularFile is executable, cat would print its content).

      • Running safeCat.sh /bin/ls (assuming /bin/ls is executable, cat would attempt to print its binary content, leading to control characters, or in context of the example, no desired output).

    if then else fi
    • Purpose: Executes one block of STATEMENTS-YES if the CONDITION is true, and a different block of STATEMENTS-NO if the CONDITION is false.

    • Syntax:
      bash if [ CONDITION ]; then STATEMENTS-YES else STATEMENTS-NO fi

    • Flowchart: Condition \rightarrowYesYes\rightarrowStatementsYesStatements-Yes\rightarrowEnd<code>if</code><br>ConditionEnd <code>if</code><br>Condition\rightarrowNoNo\rightarrowStatementsNoStatements-No\rightarrow End if

    • Example Script (safeCat.sh):bash #!/bin/bash if [ -x "$1" ]; then cat "$1" else echo "Executable: not printing $1" fi

      • Running safeCat.sh regularFile (if executable) \rightarrowPrints<code>regularFile</code>scontent.</p></li><li><p>Running<code>safeCat.sh/bin/ls</code>(ifexecutable,but<code>cat</code>isnotintendedforit)Prints <code>regularFile</code>'s content.</p></li><li><p>Running <code>safeCat.sh /bin/ls</code> (if executable, but <code>cat</code> is not intended for it)\rightarrowOutputs<code>Executable:notprinting/bin/ls</code>.</p></li></ul></li></ul><h6id="46819701b75f426a9a365f7d93223145"datatocid="46819701b75f426a9a365f7d93223145"collapsed="false"seolevelmigrated="true"><code>ifthenelifelsefi</code></h6><ul><li><p><strong>Purpose:</strong>Allowsformultipleconditionstobecheckedsequentially.Ifthefirst<code>CONDITION1</code>istrue,<code>STATEMENTS1</code>execute.Otherwise,<code>CONDITION2</code>ischecked,and<code>STATEMENTS2</code>executeiftrue.Ifneitheristrue,<code>STATEMENTS3</code>(the<code>else</code>block)execute.</p></li><li><p><strong>Syntax:</strong><br><code>bashif[CONDITION1];thenSTATEMENTS1elif[CONDITION2];thenSTATEMENTS2elseSTATEMENTS3fi</code></p></li><li><p><strong>Flowchart:</strong>Condition1Outputs <code>Executable: not printing /bin/ls</code>.</p></li></ul></li></ul><h6 id="46819701-b75f-426a-9a36-5f7d93223145" data-toc-id="46819701-b75f-426a-9a36-5f7d93223145" collapsed="false" seolevelmigrated="true"><code>if then elif else fi</code></h6><ul><li><p><strong>Purpose:</strong> Allows for multiple conditions to be checked sequentially. If the first <code>CONDITION1</code> is true, <code>STATEMENTS-1</code> execute. Otherwise, <code>CONDITION2</code> is checked, and <code>STATEMENTS-2</code> execute if true. If neither is true, <code>STATEMENTS-3</code> (the <code>else</code> block) execute.</p></li><li><p><strong>Syntax:</strong><br><code>bash if [ CONDITION1 ]; then STATEMENTS-1 elif [ CONDITION2 ]; then STATEMENTS-2 else STATEMENTS-3 fi</code></p></li><li><p><strong>Flowchart:</strong> Condition1\rightarrowYesYes\rightarrowStatements1Statements-1\rightarrowEnd<code>if</code><br>Condition1End <code>if</code><br>Condition1\rightarrowNoNo\rightarrowCondition2Condition2\rightarrowYesYes\rightarrowStatements2Statements-2\rightarrowEnd<code>if</code><br>Condition1End <code>if</code><br>Condition1\rightarrowNoNo\rightarrowCondition2Condition2\rightarrowNoNo\rightarrowStatements3Statements-3\rightarrow End if

      • Example Script (safeCat.sh):bash #!/bin/bash if [ -x "$1" ]; then cat "$1" elif [ "$1" == "/bin/ls" ]; then echo "I see /bin/ls" else echo "Executable: not printing $1" fi

        • Running safeCat.sh regularFile (if executable) \rightarrowPrints<code>regularFile</code>scontent.</p></li><li><p>Running<code>safeCat.sh/bin/ls</code>Prints <code>regularFile</code>'s content.</p></li><li><p>Running <code>safeCat.sh /bin/ls</code>\rightarrowOutputs<code>Isee/bin/ls</code>(matches<code>elif</code>condition).</p></li><li><p>Running<code>safeCat.shtestScript.sh</code>(if<code>testScript.sh</code>is<em>not</em>executableinthisspecifictestorotherwisefallsthroughthe<code>if</code>and<code>elif</code>checks)Outputs <code>I see /bin/ls</code> (matches <code>elif</code> condition).</p></li><li><p>Running <code>safeCat.sh testScript.sh</code> (if <code>testScript.sh</code> is <em>not</em> executable in this specific test or otherwise falls through the <code>if</code> and <code>elif</code> checks)\rightarrowOutputs<code>ExecutablenotprintingtestScript.sh</code>.</p></li></ul></li></ul><h6id="bbdf4d806dd3476abfb19257acb45a52"datatocid="bbdf4d806dd3476abfb19257acb45a52"collapsed="false"seolevelmigrated="true"><code>caseesac</code></h6><ul><li><p><strong>Purpose:</strong>Providesacleanwaytoexecutedifferentblocksofcodebasedonmatchinga<code>STRING</code>againstseveral<code>pattern</code>s,oftenusefulformenudrivenscriptsorhandlingdifferentfiletypes.</p></li><li><p><strong>Syntax:</strong><code>bashcaseSTRINGinpattern1)STATEMENTS1;;pattern2)STATEMENTS2;;)STATEMENTSDEFAULT;;esac</code></p><ul><li><p>Eachpatternblockendswith<code>;;</code>.</p></li><li><p>The<code>Outputs <code>Executable not printing testScript.sh</code>.</p></li></ul></li></ul><h6 id="bbdf4d80-6dd3-476a-bfb1-9257acb45a52" data-toc-id="bbdf4d80-6dd3-476a-bfb1-9257acb45a52" collapsed="false" seolevelmigrated="true"><code>case esac</code></h6><ul><li><p><strong>Purpose:</strong> Provides a clean way to execute different blocks of code based on matching a <code>STRING</code> against several <code>pattern</code>s, often useful for menu-driven scripts or handling different file types.</p></li><li><p><strong>Syntax:</strong><code>bash case STRING in pattern1) STATEMENTS-1 ;; pattern2) STATEMENTS-2 ;; *) STATEMENTS-DEFAULT ;; esac</code></p><ul><li><p>Each pattern block ends with <code>;;</code>.</p></li><li><p>The <code>*</code>patternactsasawildcard,matchinganythingnotcaughtbyprecedingpatterns(defaultcase).</p></li></ul></li><li><p><strong>Flowchart:</strong>Evaluates<code>STRING</code></code> pattern acts as a wildcard, matching anything not caught by preceding patterns (default case).</p></li></ul></li><li><p><strong>Flowchart:</strong> Evaluates <code>STRING</code>\rightarrowChecks<code>pattern1</code>Checks <code>pattern1</code>\rightarrowIfmatch,STATEMENTS1If match, STATEMENTS-1\rightarrowExit<code>case</code><br>Exit <code>case</code><br>\rightarrowElse,checks<code>pattern2</code>Else, checks <code>pattern2</code>\rightarrowIfmatch,STATEMENTS2If match, STATEMENTS-2\rightarrowExit<code>case</code><br>Exit <code>case</code><br>\rightarrowElse,checks<code>patternN</code>Else, checks <code>patternN</code>\rightarrowIfmatch,STATEMENTSNIf match, STATEMENTS-N\rightarrow Exit case

        • Example Script (caseScript.sh):bash #!/bin/bash case $1 in *sh) echo "Shell Script" ;; *.txt) echo "Text File" ;; *) echo "Some Other File" ;; esac

          • Running caseScript.sh testScript.sh \rightarrowOutputs<code>ShellScript</code>.</p></li><li><p>Running<code>caseScript.shfile.txt</code>Outputs <code>Shell Script</code>.</p></li><li><p>Running <code>caseScript.sh file.txt</code>\rightarrowOutputs<code>TextFile</code>.</p></li><li><p>Running<code>caseScript.shblah</code>Outputs <code>Text File</code>.</p></li><li><p>Running <code>caseScript.sh blah</code>\rightarrowOutputs<code>SomeOtherFile</code>.</p></li></ul></li></ul><h5id="3c9098df7afa40668f5dfb52d9a2184e"datatocid="3c9098df7afa40668f5dfb52d9a2184e"collapsed="false"seolevelmigrated="true">LoopingConstructs</h5><h6id="b1dfa7b8359f4e43bd5243352f114fef"datatocid="b1dfa7b8359f4e43bd5243352f114fef"collapsed="false"seolevelmigrated="true">OverviewofLoops</h6><ul><li><p>Loopsareusedtoperformasetof<code>STATEMENTS</code>repeatedly.</p></li><li><p>Shellscriptingoffersdifferenttypesofloops:</p><ul><li><p><code>for</code>loop:Iteratesforasetnumberofitemsinalist.</p></li><li><p><code>while</code>loop:Continuesaslongasaconditionremainstrue.</p></li><li><p><code>until</code>loop:Continuesuntilaconditionbecomestrue(i.e.,aslongasitsfalse).</p></li></ul></li></ul><h6id="6a51fa11650e4baa80d92b6621a5b0cf"datatocid="6a51fa11650e4baa80d92b6621a5b0cf"collapsed="false"seolevelmigrated="true"><code>for</code>Loop</h6><ul><li><p><strong>Purpose:</strong>Iteratesovera<code>LIST</code>ofitems,assigningeachiteminturntoa<code>VAR</code>andexecutingablockof<code>STATEMENTS</code>foreachiteration.</p></li><li><p><strong>Syntax:</strong><br><code>bashforVARinLISTdoSTATEMENTSdone</code></p></li><li><p><strong>Flowchart:</strong>Initialize<code>VAR</code>from<code>LIST</code>Outputs <code>Some Other File</code>.</p></li></ul></li></ul><h5 id="3c9098df-7afa-4066-8f5d-fb52d9a2184e" data-toc-id="3c9098df-7afa-4066-8f5d-fb52d9a2184e" collapsed="false" seolevelmigrated="true">Looping Constructs</h5><h6 id="b1dfa7b8-359f-4e43-bd52-43352f114fef" data-toc-id="b1dfa7b8-359f-4e43-bd52-43352f114fef" collapsed="false" seolevelmigrated="true">Overview of Loops</h6><ul><li><p>Loops are used to perform a set of <code>STATEMENTS</code> repeatedly.</p></li><li><p>Shell scripting offers different types of loops:</p><ul><li><p><code>for</code> loop: Iterates for a set number of items in a list.</p></li><li><p><code>while</code> loop: Continues as long as a condition remains true.</p></li><li><p><code>until</code> loop: Continues until a condition becomes true (i.e., as long as it's false).</p></li></ul></li></ul><h6 id="6a51fa11-650e-4baa-80d9-2b6621a5b0cf" data-toc-id="6a51fa11-650e-4baa-80d9-2b6621a5b0cf" collapsed="false" seolevelmigrated="true"><code>for</code> Loop</h6><ul><li><p><strong>Purpose:</strong> Iterates over a <code>LIST</code> of items, assigning each item in turn to a <code>VAR</code> and executing a block of <code>STATEMENTS</code> for each iteration.</p></li><li><p><strong>Syntax:</strong><br><code>bash for VAR in LIST do STATEMENTS done</code></p></li><li><p><strong>Flowchart:</strong> Initialize <code>VAR</code> from <code>LIST</code>\rightarrowIf<code>LIST</code>isnotempty:<br>Execute<code>STATEMENTS</code><br>Assignnextitemto<code>VAR</code><br>Repeat<br>If <code>LIST</code> is not empty:<br>Execute <code>STATEMENTS</code><br>Assign next item to <code>VAR</code><br>Repeat<br>\rightarrow If LIST is empty (or exhausted): Exit for loop.

          • Example Script (forScript.sh):

            #!/bin/bash
            for myVar in $* # Iterates through all command-line arguments ($* provides the list)
            do
                echo "$myVar"
            done
            
            • Running forScript.sh arg1 arg2 \rightarrowOutputs<code>arg1</code>(ononeline),then<code>arg2</code>(onanotherline).</p></li></ul></li><li><p><strong>SpecialFormof</strong><code>for</code><strong>Loop(withoutexplicitLIST):</strong></p><ul><li><p>Ifthe<code>inLIST</code>partisomitted,the<code>for</code>loopdefaultstoiteratingthroughallofthecommandlinearguments(<code>Outputs <code>arg1</code> (on one line), then <code>arg2</code> (on another line).</p></li></ul></li><li><p><strong>Special Form of </strong><code>for</code><strong> Loop (without explicit LIST):</strong></p><ul><li><p>If the <code>in LIST</code> part is omitted, the <code>for</code> loop defaults to iterating through all of the command-line arguments (<code>).

            • Syntax:
              bash for VAR do STATEMENTS done

            • Example (forScript.sh - special form): This script behaves identically to the previous example. bash #!/bin/bash for myVar do echo "$myVar" done

              • Running forScript.sh arg1 arg2 \rightarrowOutputs<code>arg1</code>,then<code>arg2</code>.</p></li></ul></li></ul></li></ul><h6id="e2adc614d3d444e89b1235711241f980"datatocid="e2adc614d3d444e89b1235711241f980"collapsed="false"seolevelmigrated="true"><code>while</code>Loop</h6><ul><li><p><strong>Purpose:</strong>Continuouslyexecutesablockof<code>STATEMENTS</code>aslongasaspecified<code>CONDITION</code>remainstrue.</p></li><li><p><strong>Syntax:</strong><br><code>bashwhileCONDITIONdoSTATEMENTSdone</code></p></li><li><p><strong>Flowchart:</strong>Check<code>CONDITION</code>Outputs <code>arg1</code>, then <code>arg2</code>.</p></li></ul></li></ul></li></ul><h6 id="e2adc614-d3d4-44e8-9b12-35711241f980" data-toc-id="e2adc614-d3d4-44e8-9b12-35711241f980" collapsed="false" seolevelmigrated="true"><code>while</code> Loop</h6><ul><li><p><strong>Purpose:</strong> Continuously executes a block of <code>STATEMENTS</code> as long as a specified <code>CONDITION</code> remains true.</p></li><li><p><strong>Syntax:</strong><br><code>bash while CONDITION do STATEMENTS done</code></p></li><li><p><strong>Flowchart:</strong> Check <code>CONDITION</code>\rightarrowIfTrue:<br>Execute<code>STATEMENTS</code><br>Loopbackto<code>CONDITION</code>check<br>If True:<br>Execute <code>STATEMENTS</code><br>Loop back to <code>CONDITION</code> check<br>\rightarrow If False: Exit while loop.

              • Example Script (whileScript.sh):bash #!/bin/bash counter=0 while [ "$counter" -lt 10 ] do echo "$counter" counter=$(( counter + 1 )) # Increment counter using modern arithmetic expansion done

                • Running whileScript.sh \rightarrowOutputsnumbers<code>0</code>through<code>9</code>,eachonanewline.</p></li></ul></li></ul><h6id="fabff69bd17e40b7b96d518f561506e7"datatocid="fabff69bd17e40b7b96d518f561506e7"collapsed="false"seolevelmigrated="true"><code>until</code>Loop</h6><ul><li><p><strong>Purpose:</strong>Continuouslyexecutesablockof<code>STATEMENTS</code>aslongasaspecified<code>CONDITION</code>remainsfalse(i.e.,untiltheconditionbecomestrue).</p></li><li><p><strong>Syntax:</strong><br><code>bashuntilCONDITIONdoSTATEMENTSdone</code></p></li><li><p><strong>Flowchart:</strong>Check<code>CONDITION</code>Outputs numbers <code>0</code> through <code>9</code>, each on a new line.</p></li></ul></li></ul><h6 id="fabff69b-d17e-40b7-b96d-518f561506e7" data-toc-id="fabff69b-d17e-40b7-b96d-518f561506e7" collapsed="false" seolevelmigrated="true"><code>until</code> Loop</h6><ul><li><p><strong>Purpose:</strong> Continuously executes a block of <code>STATEMENTS</code> as long as a specified <code>CONDITION</code> remains false (i.e., until the condition becomes true).</p></li><li><p><strong>Syntax:</strong><br><code>bash until CONDITION do STATEMENTS done</code></p></li><li><p><strong>Flowchart:</strong> Check <code>CONDITION</code>\rightarrowIfFalse:<br>Execute<code>STATEMENTS</code><br>Loopbackto<code>CONDITION</code>check<br>If False:<br>Execute <code>STATEMENTS</code><br>Loop back to <code>CONDITION</code> check<br>\rightarrow If True: Exit until loop.

                • Example Script (untilScript.sh):bash #!/bin/bash counter=0 until [ "$counter" -eq 10 ] do echo "$counter" counter=$(( counter + 1 )) # Increment counter using modern arithmetic expansion done

                  • Running untilScript.sh \rightarrow$$ Outputs numbers 0 through 9, each on a new line.