Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Perform command from command line inside directories from glob in bash shell script

In a bash shell script do-for.sh I want to perform a command inside all directories named in a glob using bash. This has been answered oodles of times, but I want to provide the command itself on the command line. In other words assuming I have the directories:

  • foo
  • bar

I want to enter

do-for * pwd

and have bash print the working directory inside foo and then inside bar.

From reading the umpteen answers on the web, I thought I could do this:

for dir in $1; do
  pushd ${dir}
  $2 $3 $4 $5 $6 $7 $8 $9
  popd
done

Apparently though the glob * gets expanded into the other command line arguments variable! So the first time through the loop, for $2 $3 $4 $5 $6 $7 $8 $9 I expected foo pwd but instead it appears I get foo bar!

How can I keep the glob on the command line from being expanded into the other parameters? Or is there a better way to approach this?

To make this clearer, here is how I want to use the batch file. (This works fine on the Windows batch file version, by the way.)

./do-for.sh repo-* git commit -a -m "Added new files."
like image 804
Garret Wilson Avatar asked Dec 02 '22 12:12

Garret Wilson


1 Answers

I will assume you are open to your users having to provide some kind of separator, like so

./do-for.sh repo-* -- git commit -a -m "Added new files."

Your script could do something like (this is just to explain the concept, I have not tested the actual code) :

CURRENT_DIR="$PWD"

declare -a FILES=()

for ARG in "$@"
do
  [[ "$ARG" != "--" ]] || break
  FILES+=("$ARG")
  shift
done 

if
  [[ "${1-}" = "--" ]]
then
  shift
else
  echo "You must terminate the file list with -- to separate it from the command"
  (return, exit, whatever you prefer to stop the script/function)
fi

At this point, you have all the target files in an array, and "$@" contains only the command to execute. All that is left to do is :

for FILE in "${FILES[@]-}"
do
  cd "$FILE"
  "$@"
  cd "$CURRENT_DIR"
done

Please note that this solution has the advantage that if your user forgets the "--" separator, she will be notified (as opposed to a failure due to quoting).

like image 144
Fred Avatar answered Dec 05 '22 07:12

Fred