GeekyOmega
GeekyOmega

Reputation: 1305

How to make this (l)unix script dynamically accept directory name in for-loop?

I am teaching myself more (l)unix skills and wanted to see if I could begin to write a program that will eventually read all .gz files and expand them. However, I want it to be super dynamic.

    #!/bin/bash

dir=~/derp/herp/path/goes/here

for file in $(find dir -name '*gz')
    do 
       echo $file
    done

So when I excute this file, I simply go

bash derp.sh.

I don't like this. I feel the script is too brittle. How can I rework my for loop so that I can say

bash derp.sh ~/derp/herp/path/goes/here (1) 

I tried re-coding it as follows:

for file in $*

However, I don't want to have to type in bash

derp.sh ~/derp/herp/path/goes/here/*.gz. 

How could I rewrite this so I could simply type what is in (1)? I feel I must be missing something simple?

Note

I tried

for file in $*/*.gz and that obviously did not work. I appreciate your assistance, my sources have been a wrox unix text, carpentry v5, and man files. Unfortunately, I haven't found anything that will what I want.

Thanks, GeekyOmega

Upvotes: 2

Views: 1438

Answers (2)

John1024
John1024

Reputation: 113834

for dir in "$@"
do
    for file in "$dir"/*.gz
    do 
       echo $file
    done
done

Notes:

  • In the outer loop, dir is assigned successively to each argument given on the command line. The special form "$@" is used so that the directory names that contain spaces will be processed correctly.

  • The inner loop runs over each .gz file in the given directory. By placing $dir in double-quotes, the loop will work correctly even if the directory name contains spaces. This form will also work correctly if the gz file names have spaces.

Upvotes: 2

Jeff Bowman
Jeff Bowman

Reputation: 95634

#!/bin/bash
for file in $(find "$@" -name '*.gz')
do 
   echo $file
done

You'll probably prefer "$@" instead of $*; if you were to have spaces in filenames, like with a directory named My Documents and a directory named Music, $* would effectively expand into:

find My Documents Music -name '*.gz'

where "$@" would expand into:

find "My Documents" "Music" -name '*.gz'

Requisite note: Using for file in $(find ...) is generally regarded as a bad practice, because it does tend to break if you have spaces or newlines in your directory structure. Using nested for loops (as in John's answer) is often a better idea, or using find -print0 and read as in this answer.

Upvotes: 1

Related Questions