1

I have a bash script which looks like

#!bin/bash

array to store my commands

COMMANDS=(route ls -l )

here I want to iterate through the array, run all the commands and take

screenshot of each after their execution to be put into my lab assignment file.

for (( i=0; i<${#COMMANDS[@]}; i=i+1 )); do clear "${COMMANDS[$i]}" gnome-screenshot -w -f "$i".png done

But the output looks like

Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
default         _gateway        0.0.0.0         UG    600    0        0 wlx00e02d4a265d
link-local      0.0.0.0         255.255.0.0     U     1000   0        0 docker0
172.17.0.0      0.0.0.0         255.255.0.0     U     0      0        0 docker0
192.168.43.0    0.0.0.0         255.255.255.0   U     600    0        0 wlx00e02d4a265d

5.png  Downloads       my_rust_projects  sys-info
6.png  FINAL450.pdf    Pictures          Templates

-l: command not found

How can I achieve the desired result for ls -l which is the detailed entry for each file?

2 Answers2

5

See http://mywiki.wooledge.org/BashFAQ/050, "I'm trying to put a command in a variable, but the complex cases always fail!"

This is more complex than you might think. Each command should be put into a separate array. And as bash does not implement multidimensional arrays, you need to have some management around it.

Try this:

CMD_date=( date "+%a %b %d %Y %T" )
CMD_ls=( ls -l )
CMD_sh=( env MyVar="this is a variable" sh -c 'echo "$MyVar"' )
commands=( date ls sh )

for cmd in "${commands[@]}"; do declare -n c="CMD_$cmd" # set a nameref to the array "${c[@]}" # and execute it done

namerefs were introduced in bash 4.3 -- if your bash is older, it can still work using indirect variables

for cmd in "${commands[@]}"; do
  printf -v tmp 'CMD_%s[@]' "$cmd"
  "${!tmp}"    # and execute it
done

Better: use functions:

CMD_date() {
  date "+%a %b %d %Y %T"
}
CMD_ls() {
  ls -l
}
CMD_sh() {
  env MyVar="this is a variable" sh -c 'echo "$MyVar"'
}
commands=( date ls sh )

for cmd in "${commands[@]}"; do "CMD_$cmd" done

glenn jackman
  • 85,964
0

I found a solution but don't know is it a good or bad idea. Any advice is highly appreciated:

for (( i=0; i<${#COMMANDS[@]}; i=i+1 )); do
    clear
# added bash -c in front.
bash -c &quot;${COMMANDS[$i]}&quot;
gnome-screenshot -w -f &quot;$i&quot;.png

done

  • Bad idea. You'll still get all the quoting problems because you're cramming the command and the arguments into a single string. – glenn jackman Dec 01 '20 at 16:08