Article Categories
- All Categories
-
Data Structure
-
Networking
-
RDBMS
-
Operating System
-
Java
-
MS Excel
-
iOS
-
HTML
-
CSS
-
Android
-
Python
-
C Programming
-
C++
-
C#
-
MongoDB
-
MySQL
-
Javascript
-
PHP
-
Economics & Finance
Find last Directory or file from a given path
Extracting the last directory or file name from a given path is a common task in shell scripting and Linux command-line operations. For example, from the path /tmp/dir/target, we want to extract target as the final component.
While this seems straightforward, there are several edge cases that can cause simple solutions to fail, such as trailing slashes, root directory paths, and filenames containing spaces.
Common Solutions
Since Linux filesystems use forward slashes (/) as path separators and don't allow slashes in filenames, we can treat the path as slash-separated components and extract the last non-empty element.
Text Processing Commands
$ sed 's#.*/##' <<< "/tmp/dir/target"
target
$ awk -F'/' '{print $NF}' <<< "/tmp/dir/target"
target
$ grep -o '[^/]*$' <<< "/tmp/dir/target"
target
Bash Parameter Expansion
$ INPUT="/tmp/dir/target"
$ echo ${INPUT##*/}
target
Edge Case Problems
The above solutions fail when the path has a trailing slash, because they return an empty result:
$ sed 's#.*/##' <<< "/tmp/dir/target/"
(empty output)
$ awk -F'/' '{print $NF}' <<< "/tmp/dir/target/"
(empty output)
$ INPUT="/tmp/dir/target/"
$ echo ${INPUT##*/}
(empty output)
A modified awk solution can handle trailing slashes by checking the last field and falling back to the second-to-last field if empty:
$ awk -F'/' '{ a = length($NF) ? $NF : $(NF-1); print a }' <<< "/tmp/dir/target/"
target
Corner Cases Analysis
Linux paths can have several challenging patterns that require careful handling:
| Input Path | Expected Output | Challenge |
|---|---|---|
| "/tmp/dir/target" | "target" | Standard case |
| "/tmp/dir/target/" | "target" | Trailing slash |
| "/" | "/" | Root directory |
| "/tmp/dir/ " | " " | Space in filename |
| "/tmp/dir/ /" | " " | Space with trailing slash |
A comprehensive awk solution handling all cases becomes complex:
$ awk -F'/' '$0==FS{ print $0; next }{ a = length($NF) ? $NF : $(NF-1); print a }' <<< "/"
/
Using the basename Command
The basename command from coreutils provides a robust, purpose-built solution that handles all edge cases correctly:
$ basename "/tmp/dir/target" target $ basename "/tmp/dir/target/" target $ basename "/" / $ basename "/tmp/dir/ " $ basename "/tmp/dir/ /"
The basename command has a companion called dirname that extracts the directory portion:
$ dirname "/tmp/dir/target" /tmp/dir
Comparison of Approaches
| Method | Handles Trailing Slash | Handles Root Path | Complexity | Recommended |
|---|---|---|---|---|
| Simple sed/awk/grep | No | No | Low | No |
| Complex awk | Yes | Yes | High | No |
| basename command | Yes | Yes | Low | Yes |
Conclusion
While extracting the last component from a path seems simple, proper handling of edge cases requires careful consideration. The basename command provides the most reliable and readable solution, handling trailing slashes, root directories, and special characters correctly. For production scripts, prefer basename over complex text processing commands.
