My problem here is that the parameter $0 gives the same result as ${0##*/}, and that happens after converting the x-shellscript to x-executable using the SHC program!

OS: Debiab-8.2-jessie SHC version: 3.8.7 cmd used: shc -f script.bash

The compiled script.x resides in a extra bin path (not known by sudo). Note I've created a hello world program to print the parametr $0, and it always gives me the basename!

My scriptFile contains:

((!EUID)) || exec sudo "$0"
# shellcode ...

When I execute it, I get this:

sudo: scriptName: command not found

After checking out I found that the parameter $0 is the same as ${0##*/} or $(basename $0) inside an x-executable!

How do I deal with that without putting an absolute path inside the script? Or is there something I should know when I'm compiling shell to x-executable using SHC?

  • 2
    What on earth do you mean by “x-shellscript” and “x-executable”? Commented Jan 1, 2016 at 0:10
  • @Gilles bash script and binary executable .
    – Yunus
    Commented Jan 1, 2016 at 0:11
  • 4
    But $0 is bash syntax, not something you have in an executable. Are you using some kind of “compiler” for shell scripts? That's very unusual and basically never useful. And if you are, it's absolutely the sort of thing we can't guess, you need to say what tool you're using and how. And tell us how you're executing the script, too. Commented Jan 1, 2016 at 0:13
  • converting bash script to binary executable using shc program ! sorry for lake of infos , i'm going to edit the question :)
    – Yunus
    Commented Jan 1, 2016 at 0:16
  • read the manual for sudo, you can configure it to allow specified command to be run as specified user, without a password. (because I am guessing from your code that you are trying to hide a password it at executable, because you think that if you can not extract it then I don't know how to run strings) Commented Jan 1, 2016 at 1:10

2 Answers 2


Why SHC?

First of all, why are you using SHC, given your "hobbyist" motivations? Here is an excerpt from their own description:

Upon execution, the compiled binary will decrypt and execute the code with the shell -c option. Unfortunatelly, it will not give you any speed improvement as a real C program would.

The compiled binary will still be dependent on the shell specified in the first line of the shell code (i.e. #!/bin/sh), thus shc does not create completely independent binaries.

SHC's main purpose is to protect your shell scripts from modification or inspection.

  • My opinion (I'll keep it sort of brief): Even if your motivation is the stated "main purpose" of preventing modifications, a mildly determined person can still recover (and, hence, modify) the original script! SHC essentially provides security by obscurity, which is an oft-derided strategy when used as a primary means of security. If this doesn't sound helpful, then I'd recommend ditching SHC and simply using shell scripts as the vast majority of others do. If you need real security for your shell scripts, I'd suggest asking a specific question about that, without SHC or "compilers".

The specific $0 problem

I downloaded SHC 3.8.9 from this page just to try this out.

I was not able to reproduce the problem, on Ubuntu 14.04 LTS.

echo "Hello, world. My name is \`$0'"

Test run

$ ./shc -f my_test.bash
$ ~/path/to/my_test.bash.x

Hello, world. My name is `~/path/to/my_test.bash.x'

So, clearly, our systems differ. I can try to update this answer if you post more details about your operating system, version of SHC, and specific shell script and shc commandline you used to "compile" it.

Why do you need the path?

Why does your script need to know its path? Are you storing files with the script? Does it "default" to operate on the directory it was run in if the user doesn't specify? Whether these things are good ideas or not is a matter of opinion, but knowing your motivations might be helpful in narrowing down this answer.

How to fetch the current directory

The pwd command fetches the current directory. In many cases, you can assemble the full path of your script (assuming it was run with an explicit relative path) with something like:


... which would result in a value like:


The extra ./ just means "current directory", so while it might be cosmetically unfortunate, it will not negatively affect the result.

If the script is simply in your $PATH, then you would need to use which instead of pwd, but we're already getting beyond the scope of the original question, here, so I'll conclude with a simple mention that determining pathnames can be a tricky process, especially if you need to do so in a secure manner, so that would best be left for another question with a specific problem statement along these lines.

  • thanks a lot for your time ! i'm going to add infos about os and shc version ...
    – Yunus
    Commented Jan 1, 2016 at 1:14
  • To get $PWD just use $PWD - it's not prone to command sub issues, either. And if you want a physical path there, do cd -P . first.
    – mikeserv
    Commented Jan 1, 2016 at 1:38
  • @mikeserv Indeed, since pwd implementations often just read from $PWD by default, I support your comment. Your comment also sort of highlights more of the reason why dealing with paths usually deserves special attention—more than I can reasonably provide without a more detailed question. Commented Jan 1, 2016 at 1:50
  • current directory is not what he wants, he wans the directory that has the compiled file
    – Jasen
    Commented Jan 1, 2016 at 6:33
  • 1
    @younes Thanks for the additional information in the question! Beyond what I've already suggested, the best advice I can offer is to really think about your bigger design: do you really need a binary file (much harder to distribute than a script!) and do you need to put it outside of $PATH/sudo's awareness (yet have it call sudo itself? why not just use sudo's command aliases?) I fear with your current design you will just create grief for yourself and have worse security as compared to using standard tools, which I know you're still learning. (Keep asking questions! You'll get there.) Commented Jan 1, 2016 at 8:05

it seems to be because bash (and/or ld.so) doesn't put the full name of the executable in argv[0] when it locates a binary by path search. if you specify the directory when you run it (instead of relying on path) it gets the right name.

  • 1
    The point is, argv[0]/$0 may have no relation to the program name (let alone the executable path) at all, which I may yet work into my answer. One can use any number of standard utilities/languages to trivially do the equivalent of execl("/hacked/path/modified_script", "/path/to/original_script", (char *)0); which would fool your method of using the full pathname so the script gets the wrong name instead of "the right name," as you suggested. That's why I strongly questioned the use of $0/paths in my answer, especially since the question has fairly deep roots in security. Commented Jan 1, 2016 at 8:23
  • that's a good point, expecially when combined with passwordless sudo it's ripe for exploit. (work that in too)
    – Jasen
    Commented Jan 1, 2016 at 8:33
  • no if you're a script and executed via "shebang" $0 is guaranteed to refer to the file (else how could the interpreter open the script file to run it). if you're SHC it's not shebang, and $0 is something else.
    – Jasen
    Commented Jan 1, 2016 at 12:20
  • from the propdecf of the called process, $0 and argv[0] are not the same thing. in this case argv[0] is bash and $0 is the filename of the script (with suffifient path information)
    – Jasen
    Commented Jan 1, 2016 at 12:23

You must log in to answer this question.

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