Home > Enterprise >  Prevent variable expansion in the parameter of a function to be expanded in a for loop
Prevent variable expansion in the parameter of a function to be expanded in a for loop

Time:10-28

I am building a generic function exec_all_dirs in bashrc that would run a command in multiple directories.

function exec_all_dirs() {
  curdir=$PWD
  dirs=(
    ~/dir1
    ~/dir2
    ~/dir3
  )
  for dir in ${dirs[@]};
  do
    echo "---------- $dir ---------"
    "$@"                                                          # run the command here.
  done
  cd $curdir
}

function all_func() {
  exec_all_dirs 'cd $dir && another_func_defined_in_bashrc'       # how to pass $dir
}
function all_du() {
  exec_all_dirs 'du -sh $dir'
}

How can I pass $dir as argument to exec_all_dirs so it gets expanded in the for loop?

CodePudding user response:

Instead, consider a different approach, way safer and easier to use. Work just like xargs works. Allow passing the command, as-is separated by words, to your command. Then define the work in a separate function. that way you won't have to handle putting it all in single quotes. Pass variable context "$dir" as a positional argument to the command.

exec_all_dirs() {
  local curdir dirs
  curdir=$PWD
  dirs=(
    ~/dir1
    ~/dir2
    ~/dir3
  )
  for dir in "${dirs[@]}"; do
    echo "---------- $dir ---------"
    "$@" "$dir"
  done
  cd $curdir
}

_all_func_in() {
   if cd "$1"; then
      another_func_defined_in_bashrc
   fi
}

all_func() {
  exec_all_dirs _all_func_in
}

all_du() {
  exec_all_dirs du -sh
}

Check your scripts with shellcheck. Do not use function name() - just name().


How can I pass $dir as argument to exec_all_dirs so it gets expanded in the for loop?

You can replace it yourself:

echo "$1" | sed 's/$dir/'"$dir"'/g'

You can just run eval:

eval "$@"

CodePudding user response:

Try like this:

exec_all_dirs(){
    local curdir=$PDW
    local cmd dir
    local dirs=(
        ~/dir1
        ~/dir2
        ~/dir3
    )
    for dir in ${dirs[@]}; do
        echo      "---------- $dir ---------"
        printf -v   cmd "$1" "$dir"
        bash   -c "$cmd"
    done
    cd $curdir
}

all_fu(){ exec_all_dirs 'cd %s && another_func_defined_in_bashrc'; }
all_du(){ exec_all_dirs 'du -sh %s'; }
  • Related