How do I know the script file name in a Bash script?

LinuxBashShellScripting

Linux Problem Overview


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

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

Linux Solutions


Solution 1 - Linux

me=`basename "$0"`

For reading through a symlink1, 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).


1 That is, to resolve symlinks such that when the user executes foo.sh which is actually a symlink to bar.sh, you wish to use the resolved name bar.sh rather than foo.sh.

Solution 2 - Linux

------------- SCRIPT -------------

#!/bin/bash

------------- 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 -------------

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 -------------

Solution 3 - Linux

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"

Solution 4 - Linux

$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) 

Solution 5 - Linux

If the script name has spaces in it, a more robust way is to use "$0" or "$(basename "$0")" - or on MacOS: "$(basename \"$0\")". This prevents the name from getting mangled or interpreted in any way. In general, it is good practice to always double-quote variable names in the shell.

Solution 6 - Linux

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

Solution 7 - Linux

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).

Solution 8 - Linux

I've found this line to always work, regardless of whether the file is being sourced or run as a script.

echo "${BASH_SOURCE[${#BASH_SOURCE[@]} - 1]}"

If you want to follow symlinks use readlink on the path you get above, recursively or non-recursively.

The reason the one-liner works is explained by the use of the BASH_SOURCE environment variable and its associate FUNCNAME.

> BASH_SOURCE

> An array variable whose members are the source filenames where the corresponding shell function names in the FUNCNAME array variable are defined. The shell function ${FUNCNAME[$i]} is defined in the file ${BASH_SOURCE[$i]} and called from ${BASH_SOURCE[$i+1]}.

> FUNCNAME

> An array variable containing the names of all shell functions currently in the execution call stack. The element with index 0 is the name of any currently-executing shell function. The bottom-most element (the one with the highest index) is "main". This variable exists only when a shell function is executing. Assignments to FUNCNAME have no effect and return an error status. If FUNCNAME is unset, it loses its special properties, even if it is subsequently reset.

> This variable can be used with BASH_LINENO and BASH_SOURCE. Each element of FUNCNAME has corresponding elements in BASH_LINENO and BASH_SOURCE to describe the call stack. For instance, ${FUNCNAME[$i]} was called from the file ${BASH_SOURCE[$i+1]} at line number ${BASH_LINENO[$i]}. The caller builtin displays the current call stack using this information.

[Source: Bash manual]

Solution 9 - Linux

Since some comments asked about the filename without extension, here's an example how to accomplish that:

FileName=${0##*/}
FileNameWithoutExtension=${FileName%.*}

Enjoy!

Solution 10 - Linux

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.

Solution 11 - Linux

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.

Solution 12 - Linux

this="$(dirname "$(realpath "$BASH_SOURCE")")"

This resolves symbolic links (realpath does that), handles spaces (double quotes do this), and will find the current script name even when sourced (. ./myscript) or called by other scripts ($BASH_SOURCE handles that). After all that, it is good to save this in a environment variable for re-use or for easy copy elsewhere (this=)...

Solution 13 - Linux

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

Solution 14 - Linux

if your invoke shell script like

/home/mike/runme.sh

$0 is full name

 /home/mike/runme.sh

basename $0 will get the base file name

 runme.sh

and you need to put this basic name into a variable like

filename=$(basename $0)

and add your additional text

echo "You are running $filename"

so your scripts like

/home/mike/runme.sh
#!/bin/bash 
filename=$(basename $0)
echo "You are running $filename"

Solution 15 - Linux

This works fine with ./self.sh, ~/self.sh, source self.sh, source ~/self.sh:

#!/usr/bin/env bash

self=$(readlink -f "${BASH_SOURCE[0]}")
basename=$(basename "$self")

echo "$self"
echo "$basename"

Credits: I combined multiple answers to get this one.

Solution 16 - Linux

echo "$(basename "`test -L ${BASH_SOURCE[0]} \
                   && readlink ${BASH_SOURCE[0]} \
                   || echo ${BASH_SOURCE[0]}`")"

Solution 17 - Linux

In bash you can get the script file name using $0. Generally $1, $2 etc are to access CLI arguments. Similarly $0 is to access the name which triggers the script(script file name).

#!/bin/bash
echo "You are running $0"
...
...

If you invoke the script with path like /path/to/script.sh then $0 also will give the filename with path. In that case need to use $(basename $0) to get only script file name.

Solution 18 - Linux

Short, clear and simple, in my_script.sh

#!/bin/bash

running_file_name=$(basename "$0")

echo "You are running '$running_file_name' file."

Out put:

./my_script.sh
You are running 'my_script.sh' file.

Solution 19 - Linux

Info thanks to Bill Hernandez. I added some preferences I'm adopting.

#!/bin/bash
function Usage(){
    echo " Usage: show_parameters [ arg1 ][ arg2 ]"
}
[[ ${#2} -eq 0 ]] && Usage || {
    echo
    echo "# arguments called with ---->  ${@}     "
    echo "# \$1 ----------------------->  $1       "
    echo "# \$2 ----------------------->  $2       "
    echo "# path to me --------------->  ${0}     " | sed "s/$USER/\$USER/g"
    echo "# parent path -------------->  ${0%/*}  " | sed "s/$USER/\$USER/g"
    echo "# my name ------------------>  ${0##*/} "
    echo
}

Cheers

Solution 20 - Linux

Here is what I came up with, inspired by Dimitre Radoulov's answer (which I upvoted, by the way).

script="$BASH_SOURCE"
[ -z "$BASH_SOURCE" ] && script="$0"

echo "Called $script with $# argument(s)"

regardless of the way you call your script

. path/to/script.sh

or

./path/to/script.sh

Solution 21 - Linux

$0 will give the name of the script you are running. Create a script file and add following code

#!/bin/bash
echo "Name of the file is $0"

then run from terminal like this

./file_name.sh

Solution 22 - Linux

echo "You are running $0"

Solution 23 - Linux

DIRECTORY=$(cd `dirname $0` && pwd)

I got the above from another Stack Overflow question, Can a Bash script tell what directory it's stored in?, but I think it's useful for this topic as well.

Solution 24 - Linux

somthing like this?

export LC_ALL=en_US.UTF-8
#!/bin/bash
#!/bin/sh

#----------------------------------------------------------------------
start_trash(){
ver="htrash.sh v0.0.4"
$TRASH_DIR  # url to trash $MY_USER
$TRASH_SIZE # Show Trash Folder Size

echo "Would you like to empty Trash  [y/n]?"
read ans
if [ $ans = y -o $ans = Y -o $ans = yes -o $ans = Yes -o $ans = YES ]
then
echo "'yes'"
cd $TRASH_DIR && $EMPTY_TRASH
fi
if [ $ans = n -o $ans = N -o $ans = no -o $ans = No -o $ans = NO ]
then
echo "'no'"
fi
 return $TRUE
} 
#-----------------------------------------------------------------------

start_help(){
echo "HELP COMMANDS-----------------------------"
echo "htest www                 open a homepage "
echo "htest trash               empty trash     "
 return $TRUE
} #end Help
#-----------------------------------------------#

homepage=""

return $TRUE
} #end cpdebtemp

# -Case start
# if no command line arg given
# set val to Unknown
if [ -z $1 ]
then
  val="*** Unknown  ***"
elif [ -n $1 ]
then
# otherwise make first arg as val
  val=$1
fi
# use case statement to make decision for rental
case $val in
   "trash") start_trash ;;
   "help") start_help ;;
   "www") firefox $homepage ;;
   *) echo "Sorry, I can not get a $val   for you!";;
esac
# Case stop

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionMa99uSView Question on Stackoverflow
Solution 1 - LinuxTanktalusView Answer on Stackoverflow
Solution 2 - LinuxBill HernandezView Answer on Stackoverflow
Solution 3 - LinuxDimitre RadoulovView Answer on Stackoverflow
Solution 4 - LinuxZainkaView Answer on Stackoverflow
Solution 5 - LinuxJosh LeeView Answer on Stackoverflow
Solution 6 - LinuxMr. MuskratView Answer on Stackoverflow
Solution 7 - LinuxTravis B. HartwellView Answer on Stackoverflow
Solution 8 - Linuxgkb0986View Answer on Stackoverflow
Solution 9 - LinuxSimon MattesView Answer on Stackoverflow
Solution 10 - LinuxJim DoddView Answer on Stackoverflow
Solution 11 - LinuxsimonView Answer on Stackoverflow
Solution 12 - Linuxjcalfee314View Answer on Stackoverflow
Solution 13 - LinuxVolkAView Answer on Stackoverflow
Solution 14 - LinuxLawrenceLiView Answer on Stackoverflow
Solution 15 - LinuxNishantView Answer on Stackoverflow
Solution 16 - Linuxecwpz91View Answer on Stackoverflow
Solution 17 - LinuxrashokView Answer on Stackoverflow
Solution 18 - LinuxBơ Loong A NhứiView Answer on Stackoverflow
Solution 19 - LinuxlinxuserView Answer on Stackoverflow
Solution 20 - LinuxSalathiel GenèseView Answer on Stackoverflow
Solution 21 - LinuxAli Yar KhanView Answer on Stackoverflow
Solution 22 - LinuxmmacaulayView Answer on Stackoverflow
Solution 23 - LinuxKoter84View Answer on Stackoverflow
Solution 24 - LinuxhyntView Answer on Stackoverflow