1

I have a program to list database files.

It is called direkly from the shell like

db filename

to list the whole file, or like

db 'filename :: conditions'

to list only selected elements ...


Another way is to call it with a file, wich contains all parameters.

db < parameterfile

The content is like (quite the same as the content in '' above):

filename
::
conditions

Now I woud like do make such a file executable. So that i can call just ./parameterfile.

To use a shebang #!/usr/bin/env db failed, because # is not a comment sign, I think. I got the error message

db - Line 1 near ""#.//r" - " - syntax error

shell returned 26

Is there a one-liner to do this?

3 Answers 3

3

Use awk as a shebang wrapper:

#! /usr/bin/awk BEGIN{getline;cmd="db"}{print|cmd}END{exit(close(cmd))}

... "db" commands here ...

If your script is not supposed to be run directly via execve(2) but only via the shell (or via commands like find -exec) you have a lot more options, including making it executable without prepending it a shebang, and keep it as a valid command script for whatever language that db command understands. It all depends on what that language is. For instance, if comment lines in that language start with // (as in C++), you can use:

// 2>/dev/null; exec db "$0" "$@"

... "db" commands here ...
2

You could write a shell script that removes the shebang line, if any, and passes the result to db. Place this script in a directory of your PATH. Otherwise you might have to specify the full path of the script in the shebang line. Use this script as the interpreter for your parameterfile.

Example script runparam to remove the first line if it is a shebang line:

#!/bin/sh
awk 'FNR>1 || ! /^#!/' "$@" | db

Example parameterfile:

#!/usr/bin/env runparam
filename
::
conditions

You can run it as

./parameterfile

In this case the script can assume that there will always be a shebang line.

You could also call the script directly with a parameterfile in the same way as you would call db, but this has no advantage.

runparam parameterfile
runparam parameterfile1 parameterfile2 [...]
runparam < parameterfile

If you will never call runparam with a file that doesn't contain a shebang line, you can use tail instead of awk to unconditionally remove the first line. This might be faster.

#!/bin/sh
tail -n+2 | db
3
  • Works fine, thanks :) So I can use each: ./parameterfile, runparam < parameterfile or even runparam parameterfile.
    – Andy A.
    Sep 27, 2021 at 6:04
  • @AndyA. Please don't write additional requirements in comments. As this question already has an accepted answer, the best way is to ask a new question with a reference to this one. Show the existing script and ask how to improve it. Show some example input and the resulting data that should get passed to db. Alternatively, edit your question, make clear that you edited it after accepting an answer and append the additional requirement in the same way. A shebang is also a comment, so your sed script would remove it without using awk. Try to understand the awk script .
    – Bodo
    Sep 29, 2021 at 10:39
  • @AndyA. Yes, you can delete the comment. Comments are intended for suggestions to improve the question/answer or to ask for clarification.
    – Bodo
    Sep 29, 2021 at 11:47
2

Just make it a shell script. Either something like:

exec db << 'EOF'
filename
::
conditions
EOF

(depending on the shell, that either puts the contents of that here document into a tempfile which is made the stdin of the process that will run db and deleted before db is executed, or a pipe with a shell process feeding the data through it).

Or:

tail -n+2 < "$0" | db
filename
::
conditions

Here with a pipe (or possibly socketpair with ksh93) between tail and db.

Or:

exec < "$0"; IFS= read -r ignore; exec db
filename
::
conditions

Here with db's stdin being directly opened on the script, with the first line skipped with read. That would be the most efficient.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .