|
|
|
|
||||||
| comp.unix.shell Using and programming the Unix shell. |
![]() |
|
|
LinkBack | Outils de la discussion |
|
|
#1 |
|
Messages: n/a
Hébergeur: |
I am attempting to write a wrapper shell script that invokes a program
along with file arguments. For example, I could invoke a text editor with two file arguments by running my script as follows: > ./wrapper1.sh file.txt 'file 2.txt' Two important requirements are that: 1) I can pass as many file arguments as I wish, and 2) the file names can include spaces. A simple, effective solution is the following script. ----------- wrapper1.sh ----------- #!/bin/sh -x PROGRAM=xemacs $PROGRAM "$@" In addition to file arguments, I would also like to pass flags to my wrapper script, eg: > ./wrapper2.sh -flag file.txt 'file 2.txt' I attempted to modify my script as follows: ----------- wrapper2.sh ----------- #!/bin/sh -x PROGRAM=xemacs files= flags= for arg do case "$arg" in -*) flags="$arg $flags" ;; *) files="$arg $files" ;; esac done $PROGRAM "$files" The script now places all flag arguments in the "flags" variable (which I will use for further processing in my final script), and all file arguments in the "files" variable. Alas, running the script with the two file arguments file.txt and 'file 2.txt' as shown earlier results in xemacs being launched with a single file argument named "file 2.txt file.txt". If I modify the last line in wrapper2.sh as follows: $PROGRAM $files xemacs is launched with three file arguments: "file", "2.txt", and "file.txt". How can I modify wrapper2.sh so that it properly passes file arguments to the program? |
|
|
|
#2 |
|
Messages: n/a
Hébergeur: |
On 2007-07-16, mfuhrer wrote:
> I am attempting to write a wrapper shell script that invokes a program > along with file arguments. For example, I could invoke a text editor > with two file arguments by running my script as follows: > >> ./wrapper1.sh file.txt 'file 2.txt' > > Two important requirements are that: > 1) I can pass as many file arguments as I wish, and > 2) the file names can include spaces. > > A simple, effective solution is the following script. > > ----------- > wrapper1.sh > ----------- > #!/bin/sh -x > > PROGRAM=xemacs > $PROGRAM "$@" > > > In addition to file arguments, I would also like to pass flags to my > wrapper script, eg: > >> ./wrapper2.sh -flag file.txt 'file 2.txt' > > I attempted to modify my script as follows: > > ----------- > wrapper2.sh > ----------- > #!/bin/sh -x > > PROGRAM=xemacs > files= > flags= > > for arg > do > case "$arg" in > -*) flags="$arg $flags" ;; > *) files="$arg $files" ;; > esac > done > > $PROGRAM "$files" > > > The script now places all flag arguments in the "flags" variable > (which I will use for further processing in my final script), and all > file arguments in the "files" variable. Alas, running the script with > the two file arguments file.txt and 'file 2.txt' as shown earlier > results in xemacs being launched with a single file argument named > "file 2.txt file.txt". If I modify the last line in wrapper2.sh as > follows: > > $PROGRAM $files > > xemacs is launched with three file arguments: "file", "2.txt", and > "file.txt". > > How can I modify wrapper2.sh so that it properly passes file arguments > to the program? Use single letters for the options and use getopts to process them: optstring=a:b ## list options here; colon follows those that take args while getopts "$optstring" opt do case opt in a) a_flag=1 ;; b) b_val=$OPTARG ;; *) echo "Invalid option: $opt" >&2; exit 1 ;; esac done shift "$(( $OPTIND - 1 ))" ## The remaining arguments contain the file names If you really want long options, use something like this: opts= for x in "$@" do case $1 in -*) opts="$opts $1"; shift ;; *) break ;; esac done If you want to allow the options to be intermingled with the filenames: opts= for x in "$@" do case $1 in -*) opts="$opts $1"; shift ;; *) file=$1 shift set -- "$@" "$file" ;; esac done -- Chris F.A. Johnson, author <http://cfaj.freeshell.org/shell/> Shell Scripting Recipes: A Problem-Solution Approach (2005, Apress) ===== My code in this post, if any, assumes the POSIX locale ===== and is released under the GNU General Public Licence |
|
|
|
#3 |
|
Messages: n/a
Hébergeur: |
On Sun, 15 Jul 2007 23:32:46 -0400, Chris F.A. Johnson wrote:
> On 2007-07-16, mfuhrer wrote: >> I am attempting to write a wrapper shell script that invokes a program >> along with file arguments. For example, I could invoke a text editor >> with two file arguments by running my script as follows: >> >>> ./wrapper1.sh file.txt 'file 2.txt' >> >> Two important requirements are that: >> 1) I can pass as many file arguments as I wish, and 2) the file names >> can include spaces. >> >> A simple, effective solution is the following script. >> >> ----------- >> wrapper1.sh >> ----------- >> #!/bin/sh -x >> >> PROGRAM=xemacs >> $PROGRAM "$@" >> >> >> In addition to file arguments, I would also like to pass flags to my >> wrapper script, eg: >> >>> ./wrapper2.sh -flag file.txt 'file 2.txt' >> >> I attempted to modify my script as follows: >> >> ----------- >> wrapper2.sh >> ----------- >> #!/bin/sh -x >> >> PROGRAM=xemacs >> files= >> flags= >> >> for arg >> do >> case "$arg" in >> -*) flags="$arg $flags" ;; >> *) files="$arg $files" ;; >> esac >> done >> >> $PROGRAM "$files" >> >> >> The script now places all flag arguments in the "flags" variable (which >> I will use for further processing in my final script), and all file >> arguments in the "files" variable. Alas, running the script with the >> two file arguments file.txt and 'file 2.txt' as shown earlier results >> in xemacs being launched with a single file argument named "file 2.txt >> file.txt". If I modify the last line in wrapper2.sh as follows: >> >> $PROGRAM $files >> >> xemacs is launched with three file arguments: "file", "2.txt", and >> "file.txt". >> >> How can I modify wrapper2.sh so that it properly passes file arguments >> to the program? > > Use single letters for the options and use getopts to process them: > > optstring=a:b ## list options here; colon follows those that take args > > while getopts "$optstring" opt > do > case opt in > a) a_flag=1 ;; > b) b_val=$OPTARG ;; > *) echo "Invalid option: $opt" >&2; exit 1 ;; > esac > done > shift "$(( $OPTIND - 1 ))" > > ## The remaining arguments contain the file names > > > If you really want long options, use something like this: > > opts= > for x in "$@" > do > case $1 in > -*) opts="$opts $1"; shift ;; > *) break ;; > esac > done > > > If you want to allow the options to be intermingled with the > filenames: > > opts= > for x in "$@" > do > case $1 in > -*) opts="$opts $1"; shift ;; > *) file=$1 > shift > set -- "$@" "$file" > ;; > esac > done This advice comes down to "use an array to hold your filenames, rather than a string". The original Bourne shell effectively only had a single array, the one referenced by "$@". Modern POSIX shells have as many arrays as you want. If your flags can have spaces in them, then you should accumulate them in a second array. |
|
|
|
#4 |
|
Messages: n/a
Hébergeur: |
On 2007-07-16, Icarus Sparry wrote:
.... > This advice comes down to "use an array to hold your filenames, rather > than a string". The original Bourne shell effectively only had a single > array, the one referenced by "$@". Modern POSIX shells have as many > arrays as you want. POSIX shells have no more arrays than the Bourne shell. Bash and ksh have integer arrays; ksh93 also has associative arrays. -- Chris F.A. Johnson, author <http://cfaj.freeshell.org/shell/> Shell Scripting Recipes: A Problem-Solution Approach (2005, Apress) ===== My code in this post, if any, assumes the POSIX locale ===== and is released under the GNU General Public Licence |
|
|
|
#5 |
|
Messages: n/a
Hébergeur: |
On Jul 15, 10:54 pm, Icarus Sparry <use...@icarus.freeuk.com> wrote:
> This advice comes down to "use an array to hold your filenames, rather > than a string". The original Bourne shell effectively only had a single > array, the one referenced by "$@". Modern POSIX shells have as many > arrays as you want. If your flags can have spaces in them, then you > should accumulate them in a second array. Interesting, I never realized $@ was an array. In the past I was puzzled why something like files="$@" xemacs "$files" never produced the same result as xemacs "$@" Given the array explanation, I now realize that the correct solution is: files=("$@") $PROGRAM "${files[@]}" It all starts to gel. Thanks! Martin |
|
|
|
#6 |
|
Messages: n/a
Hébergeur: |
On Jul 15, 9:32 pm, "Chris F.A. Johnson" <cfajohn...@gmail.com> wrote:
> If you want to allow the options to be intermingled with the > filenames: > > opts= > for x in "$@" > do > case $1 in > -*) opts="$opts $1"; shift ;; > *) file=$1 > shift > set -- "$@" "$file" > ;; > esac > done Chris - thanks for your thorough reply! These are exactly the solutions I was looking for; the last one is particularly useful for what I want to accomplish. Thanks again, Martin |
|
|
|
#7 |
|
Messages: n/a
Hébergeur: |
On 2007-07-16, mfuhrer wrote:
> On Jul 15, 10:54 pm, Icarus Sparry <use...@icarus.freeuk.com> wrote: >> This advice comes down to "use an array to hold your filenames, rather >> than a string". The original Bourne shell effectively only had a single >> array, the one referenced by "$@". Modern POSIX shells have as many >> arrays as you want. If your flags can have spaces in them, then you >> should accumulate them in a second array. > > Interesting, I never realized $@ was an array. It's not, but "$@" is. The quotes are important, > In the past I was > puzzled why something like > > files="$@" > xemacs "$files" > > never produced the same result as > > xemacs "$@" > > Given the array explanation, I now realize that the correct solution > is: > > files=("$@") > $PROGRAM "${files[@]}" That is not part of the POSIX standard; in a simple instance like that, use (in *any* Bourne-type shell): $PROGRAM "$@" -- Chris F.A. Johnson, author <http://cfaj.freeshell.org/shell/> Shell Scripting Recipes: A Problem-Solution Approach (2005, Apress) ===== My code in this post, if any, assumes the POSIX locale ===== and is released under the GNU General Public Licence |
|
![]() |
| Outils de la discussion | |
|
|