Monday, May 21, 2012

In the bash script how do I know the script file name?


How can I determine the name of the bash script file inside the script itself?





Like if my script is in file runme.sh, than how would I make it to display "You are running runme.sh" message without hardcodding that?



Thanks,


Source: Tips4all

13 comments:

  1. me=`basename $0`


    For reading through a symlink, which is usually not what you want (you usually don't want to confuse the user this way), try:

    me="$(basename "$(test -L "$0" && readlink "$0" || echo "$0")")"


    IMO, that'll produce confusing output. "I ran foo.sh, but it's saying I'm running bar.sh!? Must be a bug!" Besides, one of the purposes of having differently-named symlinks is to provide different functionality based on the name it's called as (think gzip and gunzip on some platforms).

    ReplyDelete
  2. With bash >= 3 the following works:

    $ ./s
    $0 is: ./s
    $BASH_SOURCE is: ./s
    $ . ./s
    $0 is: bash
    $BASH_SOURCE is: ./s

    $ cat s
    #!/bin/bash

    printf '$0 is: %s\n$BASH_SOURCE is: %s\n' "$0" "$BASH_SOURCE"

    ReplyDelete
  3. If the script name has spaces in it, a more robust way is to use "$0" or "$(basename "$0")" to prevent the name from getting mangled or interpreted in any way. In general, it is good practice to always quote variable names in the shell.

    ReplyDelete
  4. # ------------- SCRIPT ------------- #

    #!/bin/bash

    echo
    echo "# arguments called with ----> ${@} "
    echo "# \$1 ----------------------> $1 "
    echo "# \$2 ----------------------> $2 "
    echo "# path to me ---------------> ${0} "
    echo "# parent path --------------> ${0%/*} "
    echo "# my name ------------------> ${0##*/} "
    echo
    exit

    # ------------- CALLED ------------- #

    # Notice on the next line, the first argument is called within double,
    # and single quotes, since it contains two words

    $ /misc/shell_scripts/check_root/show_parms.sh "'hello there'" "'william'"

    # ------------- RESULTS ------------- #

    # arguments called with ---> 'hello there' 'william'
    # $1 ----------------------> 'hello there'
    # $2 ----------------------> 'william'
    # path to me --------------> /misc/shell_scripts/check_root/show_parms.sh
    # parent path -------------> /misc/shell_scripts/check_root
    # my name -----------------> show_parms.sh

    # ------------- END ------------- #

    ReplyDelete
  5. To answer Chris Conway, on Linux (at least) you would do this:

    echo $(basename $(readlink -nf $0))


    readlink prints out the value of a symbolic link. If it isn't a symbolic link, it prints the file name. -n tells it to not print a newline. -f tells it to follow the link completely (if a symbolic link was a link to another link, it would resolve that one as well).

    ReplyDelete
  6. These answers are correct for the cases they state but there is a still a problem if you run the script from another script using the 'source' keyword (so that it runs in the same shell). In this case, you get the $0 of the calling script. And in this case, I don't think it is possible to get the name of the script itself.

    This is an edge case and should not be taken TOO seriously. If you run the script from another script directly (without 'source'), using $0 will work.

    ReplyDelete
  7. If you want it without the path then you would use ${0##*/}

    ReplyDelete
  8. $BASH_SOURCE gives the correct answer when sourcing the script.
    This however includes the path so to get the scripts filename only, use

    $(basename $BASH_SOURCE)

    ReplyDelete
  9. You can use $0 to determine your script name (with full path) - to get the script name only you can trim that variable with

    basename $0

    ReplyDelete
  10. Re: Tanktalus's (accepted) answer above, a slightly cleaner way is to use:

    me=$(readlink --canonicalize --no-newline $0)


    If your script has been sourced from another bash script, you can use:

    me=$(readlink --canonicalize --no-newline $BASH_SOURCE)


    I agree that it would be confusing to dereference symlinks if your objective is to provide feedback to the user, but there are occasions when you do need to get the canonical name to a script or other file, and this is the best way, imo.

    ReplyDelete
  11. $0 doesn't answer the question (as I understand it). A demonstration:


    $ cat script.sh
    #! /bin/sh
    echo `basename $0`
    $ ./script.sh
    script.sh
    $ ln script.sh linktoscript
    $ ./linktoscript
    linktoscript


    How does one get ./linktoscript to print out script.sh?

    [EDIT] Per @ephemient in comments above, though the symbolic link thing may seem contrived, it is possible to fiddle with $0 such that it does not represent a filesystem resource. The OP is a bit ambiguous about what he wanted.

    ReplyDelete
  12. DIRECTORY=$(cd `dirname $0` && pwd)


    i got the above from another stackoverflow question... can a bash script tell what directory its in but i think it's usefull for this topic as well

    ReplyDelete