Amorphous
Amorphous

Reputation: 772

shebang under linux does not split arguments

I have kotlin script (but it can be any Linux command with arguments) for example:

#!/usr/bin/env kotlinc -script
println("hello world")

When I run it in Ubuntu I get:

/usr/bin/env: ‘kotlinc -script’: No such file or directory

but when I run in command line:

/usr/bin/env kotlinc -script

It works. It is no problem with finding path because script:

#!/usr/bin/env kotlinc
println("hello world")

works

For some reason under Ubuntu "#!/usr/bin/env kotlinc -script" treats "kotlinc -script" as single argument. But only in shell script header.

I need explicitly to run my script "#!/usr/bin/env kotlinc -script" because I want it to run properly on other distributions end environments where "kotlin" is in $PATH.

Is there a bug in Ubuntu coreutils or sth? Is there a way to fix it?

Upvotes: 5

Views: 879

Answers (4)

Jeffrey Blattman
Jeffrey Blattman

Reputation: 22647

#!/usr/bin/env -S kotlinc -script
println("hello world")

Note the file must have the .kts extension.

The real problem is lack of a dependency management system ala Groovy Grape. Doing anything interesting in Kotlin (or Java) means pulling in a multitude of direct and transitive dependencies. Even figuring out and finding the transitive dependencies is a chore, let alone trying to find a way to package them in a way where the script will be runnable by people without them updating their environment.

Upvotes: 0

Agapas
Agapas

Reputation: 111

Starting with coreutils 8.30 (released July 2018) you can use the -S flag, which means “process and split into separate arguments”:

#!/usr/bin/env -S command arg1 arg2 ...

You may want to upgrade your coreutils if it’s too old. As you tagged with ubuntu, you can check your coreutils version with:

apt-cache policy coreutils

Upvotes: 11

Johanno
Johanno

Reputation: 116

For me the solution was to install kotlin, since I did not yet have installed it and just downloaded https://github.com/bernaferrari/GradleKotlinConverter and thought it should work.

sudo snap install kotlin --classic

Upvotes: 0

hek2mgl
hek2mgl

Reputation: 158210

On Linux, you can't pass more than one argument via the shebang line. All arguments will be passed as a single string to the executable:

#!/bin/foo -a -b -c

will pass one option "-a -b -c" to /bin/foo, plus the contents of the file. Like if you would call:

/bin/foo '-a -b -c' contents-of-file.txt

The behaviour should be the same on most unix derivates nowadays, but it can differ, I haven't tested them all :)

It's hard to find proper documentation for this, the best I could quickly find was this: https://www.in-ulm.de/~mascheck/various/shebang/#splitting


As a workaround you would normally create a shell wrapper:

#!/bin/bash
exec kotlin --arg1 --arg2 ... /path/to/kotlin-script

Upvotes: 5

Related Questions