1

If I need to pass command line arguments from a bash script to a command without change, here is my script:

args=("$@")
mycommand "${args[@]}"

If I need to split the command line arguments from a bash script into two groups, for two commands, for example,

$ myscript -s "-o pid,tname,time,ucmd" -g "-d, -u t -t pts/4"

here is myscript

while getopts ":s:g:" opt; do                                                                                                                                                 
    case $opt in                                                                                 
        s) 
            argss="$OPTARG"
            ;;
        g) 
            argsg="$OPTARG"
            ;;
    esac
done

ps -p $(pgrep $argsg) $argss

So the call to the script is effectively the same as:

$ ps -p $(pgrep -d, -u t -t pts/4) -o pid,tname,time,ucmd

The script doesn't have double quotes around the expansions of the arguments, since it relies on the assumption that the whitespaces in $argsg and $argss exactly separate the arguments. As many already know, the assumption may sometimes fail to hold: an argument may contain whitespace. If there were just one command to pass arguments to, I would have used an array (at the beginning of this post). So is there a better way to wrap the two commands together?

By the way, I am trying to wrap ps with pgrep to allow me to AND the conditions for selecting processes. It doesn't seem necessary to write such a script (doesn't seem to simplify much), but I can save this script as a reminder when I don't remember it, and I may have other cases which makes it seem more necessary when I don't have better idea.

Thanks.

1

Pass everyone of the arguments as an independent argument on the command line and take advantage of the option processing loop to decide to with array each argument should be added:

 #!/bin/bash
 for opt; do
    if     [[ $opt == -s ]]; then sel=s; continue; fi
    if     [[ $opt == -g ]]; then sel=g; continue; fi

    if     [[ $sel == s  ]]; then argss+=("$opt");
    elif   [[ $sel == g  ]]; then argsg+=("$opt");
    else
           echo "There is an error with the value of val=$val"
           exit 3
    fi
 done

 echo pgrep "${argsg[@]}"
      pgrep "${argsg[@]}"

 echo ps "${argss[@]}"
      ps "${argss[@]}" -p "$(pgrep "${argsg[@]}")"

Write options as you would write for each program indepently on the command line.

Execute it like:

myscript -s -o pid,tname,time,ucmd -g -d, -u t -t pts/4

You will have to test it more deeply as I just tested some basic conditions. It will fail if the output of pgrep is null (no list of process IPs) as your original command did. Don't know if you wanted that condition to happen.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.