How can I create and use a backup copy of all input args ("$@") in bash?
Asked Answered
S

1

1

I need the ability to back up and then later use (both to read and print and to pass to another command as arguments) 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://mcmap.net/q/40490/-how-do-i-parse-command-line-arguments-in-bash
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
  3. ...and culminated in this rapid find-and-replace tool wrapper I wrote around Ripgrep.
Snippet answered 4/1, 2022 at 0:4 Comment(0)
D
5

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[@]}"
Dobrinsky answered 4/1, 2022 at 0:12 Comment(4)
Thank you. I credited you in this commit :) github.com/ElectricRCAircraftGuy/eRCaGuy_hello_world/commit/…Snippet
And here is the culmination of what this was for: rgr (Ripgrep Replace--allows ripgrep to find and replace on your disk). It finally works!Snippet
I've used and referenced this answer a lot since you gave it. It clarified a lot of things for me and allowed me to more-fully use bash arrays, which are extremely useful in so many cases. As a result of your answer, I've now been able to answer this as well, which I recently needed myself: Passing arrays as parameters in bash. Thanks again.Snippet
I'm glad it helped you so much. It's nice to hear. Cheers!Dobrinsky

© 2022 - 2024 — McMap. All rights reserved.