0

I'm trying to make some application but it's too difficult to describe it here so I simplify my problem into simpler ones.

I just want to make a script that takes two arguments: time and command. It parses arguments with getopts, waits some time and executes the given command.

I've tried to use various combinations of double-quotes, single-quotes and no quotes at all, use bash arrays (I think so) and look for similar questions but it didn't help.

script.sh

time=1
command=""
while getopts "t:x:" opt; do
  case $opt in
    t) time=$OPTARG;;
    x) command=( "$OPTARG" );; # store the command in a variable
  esac
done
sleep $time
"${command[@]}" # execute the stored command

test.sh

# script to test arguments passing
echo "1$1 2$2 3$3 4$4"

The results of executing the script should be the same as the execution of command passed in -x argument.

$./script.sh -x "./test.sh a 'b c'"
1a 2'b 3c' 4 # actual results
$./test.sh a 'b c'
1a 2b c 3 4 # expected results
J Kluseczka
  • 1,150
  • 9
  • 14

2 Answers2

1

change "${command[@]}" to eval "${command[0]}"

UtLox
  • 3,744
  • 2
  • 10
  • 13
0

Solution without eval:

#!/usr/bin/env bash

time=1
command=""
while getopts "t:x:" opt; do
  case "${opt}" in
    t)
      time="${OPTARG}"
      ;;
    x)
      command="${OPTARG}" # get the command

      # shift out already processed arguments
      shift "$(( OPTIND - 1 ))"
      # and exit the getopts loop, so remaining arguments
      # are passed to the command
      break
      ;;
    *) exit 1 ;; # Unknown option
  esac
done

sleep "${time}"
"${command}" "${@}" # execute the command with its arguments
Léa Gris
  • 17,497
  • 4
  • 32
  • 41
  • but then this command will not work: `./script.sh -x ./test.sh a "b c" -t 10`. Your solution will interpret it like `command="./test.sh a "b c" -t 10"`. Also `./script.sh -t 10 -x './test.sh a "b c"'` will not work. – J Kluseczka Jul 20 '19 at 14:18