Monday, January 3, 2022

[SOLVED] How can I create and use a backup copy of all input args ("$@") in bash?

Issue

I need the ability to back up and then later use all input args to a bash program, but can't figure it out. Here is my attempt:

back_up_all_input_args.sh:

#!/usr/bin/env bash

all_args1="$@"
all_args2="$(printf "%q " "$@")"

# Simulate parsing the input args here
# - see: https://stackoverflow.com/a/14203146/4561887
shift # remove 1st arg
shift # remove 2nd arg

echo "$@"
echo "$all_args1"
echo "$all_args2"

# Do another program call with all input args here
# rg "$all_args1"  # FAILS
# rg "$all_args2"  # FAILS

Sample run and output:

$ ./backup_all_input_args.sh arg1 "arg 2" "arg 3"
arg 3
arg1 arg 2 arg 3
arg1 arg\ 2 arg\ 3 

My first approach was to back up the arguments with all_args1="$@". This fails because I lose the quotes and get arg1 arg 2 arg 3. My 2nd approach was to back up the arguments with all_args2="$(printf "%q " "$@")". This fails because again, I lose the quotes, and it just so happens the first argument doesn't just need to be stuck together with the backslash like a file path, but rather, it is a regular expression argument, so it needs to remain truly unmodified. This, therefore, is not equal to the original input: arg1 arg\ 2 arg\ 3 .

References I've already studied to get this far

  1. How to keep quotes in Bash arguments?
  2. How can I preserve quotes in printing a bash script's arguments
  3. How do I parse command line arguments in Bash?

Bash demo

Update: this Q&A, now that I have an answer, contributed to these bash demos I just wrote:

  1. back_up_all_input_args.sh
  2. array_practice.sh

Solution

Add parentheses and store them in an array. This will preserve each of the arguments as separate words and avoids all the backslash escaping complexities.

all_args=("$@")

You can then pass the arguments to another command:

cmd "${all_args[@]}"

Or print them out:

printf '[%s]\n' "${all_args[@]}"

Or assign them to another array:

args_copy=("${all_args[@]}")

You can also use set restore the script's original $1, $2, etc., arguments:

set -- "${all_args[@]}"


Answered By - John Kugelman