help-bash
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: #!shebang


From: Greg Wooledge
Subject: Re: #!shebang
Date: Wed, 20 Nov 2024 07:24:52 -0500

On Wed, Nov 20, 2024 at 10:19:25 +0100, lacsaP Patatetom wrote:
> I currently store my configuration like this in `configuration.qemu` :
> ```
> -argument
> 
> - argument -option
> 
> -etc...
> ```
> 
> and I call `qemu` like this and it works as expected :
> `$ qemu $(<configuration.qemu)`

For the record, this is not "safe" in general.  It uses the shell's
default word splitting to separate the arguments, and therefore it
will fail if any of your arguments have spaces in them.

hobbit:~$ cat z
-foo
-file="a file with spaces"
-bar
hobbit:~$ args $(<z)
6 args: <-foo> <-file="a> <file> <with> <spaces"> <-bar>

Now, maybe it's impossible for qemu to receive an argument that contains
whitespace, and therefore this hack works for qemu -- I don't know.

What I do know is that there *will* be other programs for which it can
fail.  A filename argument may contain whitespace, for example.  Or
you may call "make" with an argument like CFLAGS="-g -O2" and so on.

What you're doing is more suited to eval.  As long as you recognize
that your "configuration file" is really a shell script fragment, with
real consequences if it contains command substitutions and so on, then
you might try this:

hobbit:~$ eval args "$(tr '\n' ' ' <z)"
3 args: <-foo> <-file=a file with spaces> <-bar>

All of the warnings you've heard about eval apply here.  If you're
adding other argument constructors to the same command, then eval
will apply to them as well.  Be very sure of what you're doing if
you choose this route.

So, your next question is probably going to be "how do I add comments
to this?"  Before I answer that, let's explore another approach.  We'll
start with the same file:

hobbit:~$ cat z
-foo
-file="a file with spaces"
-bar
hobbit:~$ eval "a=( $(<z) )"; args "${a[@]}"
3 args: <-foo> <-file=a file with spaces> <-bar>

In this version, I'm populating an array using the file's contents.
The eval command expands out to this:

a=( -foo
-file="a file with spaces"
-bar )

There's no need to translate the newlines in this case, as they are
allowed within an array assignment.  In fact, so are comments.  Let's
add some comments to our input file:

hobbit:~$ cat z
-foo
# a whole line comment
-file="a file with spaces"
-bar # an inline comment
-q
hobbit:~$ eval "a=( $(<z) )"; args "${a[@]}"
4 args: <-foo> <-file=a file with spaces> <-bar> <-q>

I believe that does all the things you require.  It may rule out some
trickery that you were hoping to achieve with a shebang, but I don't
care about that.  I prefer to give you an approach that won't break.

#!/bin/bash
eval "args=( $(<configuration.qemu) )"
qemu "${args[@]}"   # maybe with exec

There, nice and clean.  Or as clean as your configuration.qemu file is.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]