basename and dirname

These handy commands allow you to extract filenames and directory portions of the given paths. You could also use Parameter Expansion or cut, sed, awk, etc for such purposes. The advantage is that these commands will also handle corner cases like trailing slashes and there are handy features like removing file extensions.

Extract filename from paths

By default, the basename command will remove the leading directory component from the given path argument. Any trailing slashes will be removed before determining the portion to be extracted.

$ basename /home/learnbyexample/example_files/scores.csv scores.csv # quote the arguments when needed $ basename 'path with spaces/report.log' report.log # one or more trailing slashes will not affect the output $ basename /home/learnbyexample/example_files/ example_files

If there's no leading directory component or if slash alone is the input, the argument will be returned as is after removing any trailing slashes.

$ basename filename.txt filename.txt $ basename / /

Remove file extension

You can use the -s option to remove a suffix from the filename. Usually used to remove the file extension.

$ basename -s'.csv' /home/learnbyexample/example_files/scores.csv scores $ basename -s'_2' final_report.txt_2 final_report.txt $ basename -s'.tar.gz' /backups/jan_2021.tar.gz jan_2021 $ basename -s'.txt' purchases.txt.txt purchases.txt # -s will be ignored if it would have resulted in an empty output $ basename -s'report' /backups/report report

You can also pass the suffix to be removed after the path argument, but the -s option is preferred as it makes the intention clearer and works for multiple path arguments.

$ basename example_files/scores.csv .csv scores

Remove filename from path

By default, the dirname command removes the trailing path component (after removing any trailing slashes).

$ dirname /home/learnbyexample/example_files/scores.csv /home/learnbyexample/example_files # one or more trailing slashes will not affect the output $ dirname /home/learnbyexample/example_files/ /home/learnbyexample

Multiple arguments

The dirname command accepts multiple path arguments by default. The basename command requires -a or -s (which implies -a) to work with multiple arguments.

$ basename -a /backups/jan_2021.tar.gz /home/learnbyexample/report.log jan_2021.tar.gz report.log # -a is implied when the -s option is used $ basename -s'.txt' logs/purchases.txt logs/report.txt purchases report # dirname accepts multiple path arguments by default $ dirname /home/learnbyexample/example_files/scores.csv ../report/backups/ /home/learnbyexample/example_files ../report

Combining basename and dirname

You can use shell features like command substitution to combine the effects of the basename and dirname commands.

# extract the second last path component $ basename $(dirname /home/learnbyexample/example_files/scores.csv) example_files

NUL separator

Use the -z option if you want to use NUL character as the output path separator.

$ basename -zs'.txt' logs/purchases.txt logs/report.txt | cat -v purchases^@report^@ $ basename -z logs/purchases.txt | cat -v purchases.txt^@ $ dirname -z example_files/scores.csv ../report/backups/ | cat -v example_files^@../report^@

Exercises

1) Is the following command valid? If so, what would be the output?

$ basename -s.txt ~///test.txt///

2) Given the file path in the shell variable p, how'd you obtain the outputs shown below?

$ p='~/projects/square_tictactoe/python/game.py' ##### add your solution here ~/projects/square_tictactoe $ p='/backups/jan_2021.tar.gz' ##### add your solution here /

3) What would be the output of the basename command if the input has no leading directory component or only has the / character?

4) For the paths stored in the shell variable p, how'd you obtain the outputs shown below?

$ p='/a/b/ip.txt /c/d/e/f/op.txt' # expected output 1 ##### add your solution here ip op # expected output 2 ##### add your solution here /a/b /c/d/e/f

5) Given the file path in the shell variable p, how'd you obtain the outputs shown below?

$ p='~/projects/python/square_tictactoe/game.py' ##### add your solution here square_tictactoe $ p='/backups/aug_2024/ip.tar.gz' ##### add your solution here aug_2024