Complete Guide to Getting Script File Name in Bash Scripts

Nov 08, 2025 · Programming · 15 views · 7.8

Keywords: Bash scripting | $0 variable | basename command | symbolic links | parameter expansion | BASH_SOURCE

Abstract: This article provides a comprehensive exploration of various methods to dynamically obtain the script file name within Bash scripts, with a focus on the usage scenarios and limitations of the $0 variable. By comparing different implementations including the basename command, parameter expansion, and the BASH_SOURCE variable, it delves into key technical details such as symbolic link handling and execution environment differences. The article offers best practices for selecting appropriate solutions in different scenarios through concrete code examples, helping developers create more robust and portable shell scripts.

Fundamental Principles of Getting File Names in Bash Scripts

In Bash script development, there is often a need to dynamically obtain the current script's file name rather than hardcoding it in the code. This requirement is particularly common in scenarios such as logging, error reporting, and configuration loading. Bash provides multiple mechanisms to achieve this goal, with the most basic and commonly used being the special variable $0.

Using the $0 Variable to Get Script Name

The $0 variable in Bash scripts represents the pathname of the current script. When a script is executed directly, $0 contains the full path or relative path used when invoking the script. For example, if the script is located at /home/user/scripts/runme.sh, then $0's value would be that full path.

To extract the pure script file name, the basename command can be used:

me=$(basename "$0")
echo "You are running $me"

This code first uses the basename command to extract the file name from the full path, then stores the result in the variable me. This method is simple and effective, suitable for most常规 scenarios.

Complexities of Symbolic Link Handling

In actual deployments, scripts are often invoked through symbolic links. In such cases, $0 returns the name of the symbolic link rather than the actual script file's name. While it's possible to resolve symbolic links to obtain the real file name, this approach may cause user experience issues.

Consider the following code for handling symbolic links:

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

The logic of this code is: first check if $0 is a symbolic link (-L "$0"), if so use readlink to resolve the real path, otherwise directly use $0. However, this handling may cause user confusion because users see the command name they actually executed, while the script reports a different name.

Symbolic link naming often serves specific purposes, such as gzip and gunzip being different symbolic links pointing to the same binary file in some systems, distinguishing functionality by name. In such cases, resolving symbolic links would actually破坏 this design intent.

Alternative Approach Using Parameter Expansion

Besides using external commands like basename, Bash also provides built-in parameter expansion functionality to extract file names:

echo "Full path: ${0}"
echo "Parent directory: ${0%/*}"
echo "Script name: ${0##*/}"

This uses Bash's parameter expansion syntax: ${0%/*} removes the shortest matching pattern of /* from the end of the path, yielding the parent directory path; ${0##*/} removes the longest matching pattern of */ from the beginning of the path, yielding the pure file name. This method doesn't rely on external commands and has higher execution efficiency.

Advanced Usage of BASH_SOURCE Variable

For Bash version 3.0 and above, the BASH_SOURCE array variable provides a more reliable way to obtain script source information:

printf '$0 is: %s\n$BASH_SOURCE is: %s\n' "$0" "${BASH_SOURCE[0]}"

When a script is executed directly, $0 and ${BASH_SOURCE[0]} have the same value. But when a script is loaded via the source command (like . ./script.sh), $0 remains the parent shell's name, while BASH_SOURCE[0] still points to the actual script file. This difference makes BASH_SOURCE more reliable in complex scripts that need to distinguish execution methods.

Considerations for Special Execution Environments

In certain special execution environments, methods for obtaining script names require particular attention:

When executing scripts from standard input:

{
echo 'wc -l < /dev/null'
echo 'echo $0'
} | /bin/bash -s

Or when executing code snippets via the -c option:

/bin/bash -c 'echo $0'

In these cases, there is actually no script file, and $0's value might be the shell's name or other identifiers. Some Unix variants (like older versions of Solaris or AIX) might also not set $0 as expected.

Best Practice Recommendations

Based on the above analysis, the following best practices are recommended:

For most常规 purposes, using simple basename "$0" is sufficient. This method is straightforward and has good compatibility.

In scenarios requiring symbolic link handling, user experience should be carefully considered. Unless there is a clear business requirement to resolve the real file name, it's recommended to preserve the symbolic link's name because users expect to see the command name they actually entered.

When writing script libraries that need to be sourced,优先 use BASH_SOURCE[0] to ensure correct script path acquisition.

For scripts with high cross-platform compatibility requirements, environmental detection and fallback mechanisms are recommended:

if [ -n "${BASH_SOURCE[0]}" ]; then
    script_name=$(basename "${BASH_SOURCE[0]}")
elif [ -n "$0" ] && [ "$0" != "-bash" ]; then
    script_name=$(basename "$0")
else
    script_name="unknown_script"
fi

Practical Application Examples

Here is a complete script example demonstrating how to use these techniques in practice:

#!/bin/bash

# Get basic script information
script_name=$(basename "$0")
script_dir=$(dirname "$0")
full_path=$(readlink -f "$0")  # Get absolute path

# Output execution information
echo "Script execution information:"
echo "  Script name: $script_name"
echo "  Script directory: $script_dir"
echo "  Full path: $full_path"
echo "  Call parameters: $@"

# Use script name in logging
log_message="[$script_name] Task execution started at $(date)"
echo "$log_message" | tee -a /var/log/myapp.log

# Select different behaviors based on script name
case "$script_name" in
    backup*.sh)
        echo "Executing backup operation..."
        ;;
    deploy*.sh)
        echo "Executing deployment operation..."
        ;;
    *)
        echo "Executing default operation..."
        ;;
esac

This example shows how to comprehensively utilize various techniques to obtain and use script information, including basic file name extraction, path handling, logging, and conditional branching based on script names.

Conclusion

Obtaining script file names in Bash scripts is a fundamental yet important technical aspect. By appropriately selecting and using mechanisms like $0, basename, parameter expansion, and BASH_SOURCE, developers can create both robust and flexible shell scripts. The key lies in understanding the applicable scenarios and limitations of different methods, and choosing the most suitable solution based on specific requirements.

Copyright Notice: All rights in this article are reserved by the operators of DevGex. Reasonable sharing and citation are welcome; any reproduction, excerpting, or re-publication without prior permission is prohibited.