In Bash scripts, I frequently find this pattern useful, where I first print the command I'm about to execute, then I execute the command:
echo 'Running this cmd: ls -1 "$HOME/temp/some folder with spaces'
ls -1 "$HOME/temp/some folder with spaces"
echo 'Running this cmd: df -h'
df -h
# etc.
Notice the single quotes in the echo
command to prevent variable expansion there! The idea is that I want to print the cmd I'm running, exactly as I will type and run the command, then run it!
How do I wrap this up into a function?
Wrapping the command up into a standard bash array, and then printing and calling it, like this, sort-of works:
# Print and run the passed-in command
# USAGE:
# cmd_array=(ls -a -l -F /)
# print_and_run_cmd cmd_array
# See:
# 1. My answer on how to pass regular "indexed" and associative arrays by reference:
# https://mcmap.net/q/41290/-passing-arrays-as-parameters-in-bash and
# 1. My answer on how to pass associative arrays: https://mcmap.net/q/41561/-how-to-pass-an-associative-array-as-argument-to-a-function-in-bash
print_and_run_cmd() {
local -n array_reference="$1"
echo "Running cmd: ${cmd_array[@]}"
# run the command by calling all elements of the command array at once
${cmd_array[@]}
}
For simple commands like this it works fine:
Usage:
cmd_array=(ls -a -l -F /)
print_and_run_cmd cmd_array
Output:
Running cmd: ls -a -l -F /
(all output of that cmd is here)
But for more-complicated commands it is broken!:
Usage:
cmd_array=(ls -1 "$HOME/temp/some folder with spaces")
print_and_run_cmd cmd_array
Desired output:
Running cmd: ls -1 "$HOME/temp/some folder with spaces"
(all output of that command should be here)
Actual Output:
Running cmd: ls -1 /home/gabriel/temp/some folder with spaces
ls: cannot access '/home/gabriel/temp/some': No such file or directory
ls: cannot access 'folder': No such file or directory
ls: cannot access 'with': No such file or directory
ls: cannot access 'spaces': No such file or directory
The first problem, as you can see, is that $HOME
got expanded in the Running cmd:
line, when it shouldn't have, and the double quotes around that path argument were removed, and the 2nd problem is that the command doesn't actually run.
How do I fix these 2 problems?
References:
- my bash demo program where I have this
print_and_run_cmd
function: https://github.com/ElectricRCAircraftGuy/eRCaGuy_hello_world/blob/master/bash/argument_parsing__3_advanced__gen_prog_template.sh - where I first documented how to pass bash arrays by reference, as I do in that function:
cmd_array=(ls -1 "$HOME/temp/some folder with spaces")
should becmd_array=('ls -1 "$HOME/temp/some folder with spaces"')
becausecmd_array=(ls -1 "$HOME/temp/some folder with spaces")
runs before it runs inprint_and_run_cmd()
. The only addition being a glitch ' to keep things from running or expanding before `print_and_run_cmd() is executed – Katakana