Looping Over Arguments Passed to a Script

Problem

You want to take some set of actions for a given list of arguments. You could write your shell script to do that for one argument and use $1 to reference the parameter. But what if you’d like to do this for a whole bunch of files? You would like to be able to invoke your script like this:

actall *.txt

knowing that the shell will pattern match and build a list of filenames that match the *.txt pattern (any filename ending with .txt).

Solution

Use the shell special variable $* to refer to all of your arguments, and use that in a for loop like this:

#!/usr/bin/env bash
# cookbook filename: chmod_all.1
#
# change permissions on a bunch of files
#
for FN in $*
do
    echo changing $FN
    chmod 0750 $FN
done

Discussion

The variable $FN is our choice; we could have used any shell variable name we wanted there. The $* refers to all the arguments supplied on the command line. For example, if the user types:

$ ./actall abc.txt another.txt allmynotes.txt

the script will be invoked with $1 equal to abc.txt and $2 equal to another.txt and $3 equal to allmynotes.txt, but $* will be equal to the entire list. In other words, after the shell has substituted the list for $* in the for statement, it will be as if the script had read:

for FN in abc.txt another.txt allmynotes.txt
do
  echo changing $FN
  chmod 0750 $FN
done

The for loop will take one value at a time from the list, assign it to the variable $FN and proceed through the list of statements between the do and the done. It will then repeat that loop for each of the other values.

But you’re not finished yet! This script works fine when filenames have no spaces in them, but sometimes you encounter filenames with spaces. Read the next two recipes to see how this script can be improved.

See Also

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.139.240.142