0

I have a directory with the following files:

  • file1.jpg
  • file2.jpg
  • file3.jpg
  • file1.png
  • file2.png
  • file3.png

I have a bash function named filelist and it looks like this:

filelist() {

  if [ "$1" ]
    then
      shopt -s nullglob
      for filelist in *."$@" ; do
      echo "$filelist" >> created-file-list.txt;
      done
      echo "file created listing: " $@;
    else
      filelist=`find . -type f -name "*.*" -exec basename \{} \;`
      echo "$filelist" >> created-file-list.txt
      echo "file created listing: All Files";
  fi

}

Goal: Be able to type as many arguments as I want for example filelist jpg png and create a file with a list of files of only the extensions I used as arguments. So if I type filelist jpg it would only show a list of files that have .jpg.

Currently: My code works great with one argument thanks to $@, but when I use both jpg and png it creates the following list

  • file1.jpg
  • file2.jpg
  • file3.jpg
  • png

It looks like my for loop is only running once and only using the first argument. My suspicion is I need to count how many arguments and run the loop on each one.

An obvious fix for this is to create a long regex check like (jpg|png|jpeg|html|css) and all of the different extensions one could ever think to type. This is not ideal because I want other people to be free to type their file extensions without breaking it if they type one that I don't have identified in my regex. Dynamic is key.

2 Answers 2

1

You can rewrite your function as shown below - just loop through each extension and append the list of matching files to the output file:

filelist() {
  if [ $# -gt 0 ]; then
    shopt -s nullglob
    for ext in "$@"; do
      printf '%s\n' *."$ext" >> created-file-list.txt
      echo "created listing for extension $ext"
    done
  else
    find . -type f -name "*.*" -exec basename \{} \; >> created-file-list.txt
    echo "created listing for all files"
  fi
}

And you can invoke your function as:

filelist jpg png
Sign up to request clarification or add additional context in comments.

8 Comments

Wouldn't it make more sense to remove all the redirections and have the caller redirect filelist to a file if they want to? Then you'll obviously need to print status messages to stderr instead but that's probably a good idea regardless.
Unlike the OP's original this will overwrite, not append to, the output file(s).
There's no need for an inner loop, really. Just printf "%s\n" *.$ext
@codeforester hmmm it doesn't seem to work for me. I am either getting one or the other :/ Is the double in necessary? I am getting this as my echo file created listing for extension in file created listing for extension jpg file created listing for extension png
@codeforester sorry didn't see update. I'll check back in a sec
|
0

Try this

#!/bin/bash

while [ -n "$1" ]
  do
    echo "Current Parameter: $1 , Remaining $#"
    #Pass $1 to some bash function or do whatever
    shift
done

Using the shift you shift the args left and get the next one by reading the $1 variable.

See man bash on what shift does.

shift [n]

The positional parameters from n+1 ... are renamed to $1 .... Parameters represented by the numbers $# down to $#-n+1 are unset. n must be a non-negative number less than or equal to $#. If n is 0, no parameters are changed. If n is not given, it is assumed to be 1. If n is greater than $#, the positional parameters are not changed. The return status is greater than zero if n is greater than $# or less than zero; otherwise 0.

Or you can iterate like as follows

for this in "$@"
 do
   echo "Param = $this";
done

2 Comments

Thanks for the quick reply. Sorry for my lack of understanding here. Would I then put my for loop above your echo? I am not fully understanding how to merge our two ideas together.
You might just make a function which accepts only one of the types, and then call that function within any of the above loops in this answer.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.