Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. It's 100% free, no registration required.

I am writing a script to act on files given to the script using the $1 variable. What is the best way to loop through these files. At the moment I have hard coded the script using something like

for file in *.pdf
do 
   act on $file
done

However I would rather do this using the $1 variable Thanks Barry

share|improve this question
    
you can do for file in $1 inside the code... to ensure, shell doesn't expand *, put that argument inside single quotes –  Madhavan Kumar Aug 9 at 12:10

2 Answers 2

$1 is simply the first parameter passed to your shell script. So if you have a script myscript and I call it like this:

myscript somefile

Then $1 will be somefile. If I call it like this:

myscript *

And there happen to be files in my current directory named:

foo bar baz

Then $1 will be foo. In either case, $1 only has a single value and there is nothing to loop over.

There are a couple of ways to loop over the arguments. The most common is:

for file in "$@"; do
  echo doing something with "$file"
done

Note that $@ is not the same as "$@"; the latter is a special construct that will correctly deal with filenames that contain spaces. You could also do something like:

while [ -n "$1" ]; do
  echo doing something with "$1"
  shift
done

Here, the shift command drops the first parameter, and $2 becomes $1 (and so on). This will loop as long as $1 is non-empty. You could also use $# for this (a variable which contains the number of command line arguments):

while [ $# -gt 0 ]; do
    echo arg: "$1"
    shift
done
share|improve this answer
    
Note that the canonical (and most portable) way to write for file in "$@" is for file do. –  Stéphane Chazelas Aug 9 at 17:32
    
I have honestly never seen that syntax used in practice. Are you aware of any Bourne-ish shells that don't work properly given for file in "$@"? –  larsks Aug 9 at 17:40
    
It doesn't work properly in some versions of the Bourne shell when $# is 0. It doesn't work with the Bourne shell or pdksh when $IFS is empty (doesn't contain space for the Bourne shell). –  Stéphane Chazelas Aug 9 at 17:46

If you do

script *.pdf

*.pdf is already expanded on the command line, and $1 will only refer to the first file

for file in $1

will therefore not do what you need. You could use

for file in "$@"

instead.

See the section Special Parameters in the man bash

share|improve this answer
    
Arrgghhh!  Don't say for file in $@; that will fail if arguments contain spaces or various other special characters.  Use for file in "$@", or just plain for file for short. –  Scott Aug 9 at 13:56

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.