Reputation: 772
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
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
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
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
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