简体   繁体   中英

Bash script: expansion of argument not using $@ or $*

Using $@ you can do things to a list of files in bash. Example:

script.sh:

#!/bin/bash
list=$@
for file in $list; do _commands_; done

Then i can call this program with

~/path/to/./script dir1/{subdir1/*.dat,subdir2/*}

This argument will expand to a number of arguments that becomes $list . But now i want other arguments, say $1, $2, and this listing to be $3. So i want the expansion of dir1/{subdir1/*.dat,subdir2/*} to occur inside the script, instead of becoming many arguments. On the command line you can do this:

find dir1/{subdir1/*.dat,subdir2/*}

And get the desired output, ie a list if files. So I tried things like this:

arg1=$1
arg2=$2
list=$(find $3)
for file in $list; do _commands_; done
...

calling:

~/path/to/./script arg_1 arg_2 'dir1/{subdir1/*.dat,subdir2/*}'

But without success. Some help on how to make this list expand into a variable inside the script would be well appreciated!:)

EDIT: So answers below gave the solution using these commands:

arg1="$1"
arg2="$2"
shift 2

for f in "$@"; do echo "processing $f"; done;

But out of curiosity, is it still possible to pass the string dir1/{subdir1/*.dat,subdir2/*} to a find command (or whichever means to the same end) inside the script, without using $@ , and obtain the list that way? This could be useful eg if it is preferable to have the listing as not the first or last argument, or maybe in some other cases, even if it requires escaping characters or quoting the argument.

You can have this code in your script:

arg1="$1"
arg2="$2"
shift 2

for f in "$@"; do echo "processing $f"; done;

Then call it as:

~/path/to/script arg_1 arg_2 dir1/{subdir1/*.dat,subdir2/*}

Using shift 2 will move positional parameters 2 places thus making $3 as $1 and $4 as $2 etc. You can then directly invoke $@ to iterate the rest of the arguments.

As per help shift :

shift: shift [n]

  Shift positional parameters.

  Rename the positional parameters $N+1,$N+2 ... to $1,$2 ...  If N is

The shell expansion is performed by the shell, before your script is even called. That means you'll have to quote/escape the parameters. In the script, you can use eval to perform the expansion.

#!/bin/bash
arg1="$1" ; shift
arg2="$2" ; shift
eval "list=($@)"
for q in "${list[@]}" ; do echo "$q" ; done

$ ./a 123 456 'a{b,c}' 'd*'
ab ac d.pl docs

I don't see the point of doing the expansion inside the script in your example.

#!/bin/bash
arg1="$1" ; shift
arg2="$2" ; shift
list=("$@")
for q in "${list[@]}" ; do echo "$q" ; done

or just

#!/bin/bash
arg1="$1" ; shift
arg2="$2" ; shift
for q in "$@" ; do echo "$q" ; done

$ ./a 123 456 a{b,c} d*
ab
ac
d.pl
docs

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM