string - Extract filename and extension in Bash

ID : 294

viewed : 89

Tags : bashstringfilenamesbashbash

Top 5 Answer for string - Extract filename and extension in Bash

vote vote

92

First, get file name without the path:

filename=$(basename -- "$fullfile") extension="${filename##*.}" filename="${filename%.*}" 

Alternatively, you can focus on the last '/' of the path instead of the '.' which should work even if you have unpredictable file extensions:

filename="${fullfile##*/}" 

You may want to check the documentation :

vote vote

86

~% FILE="example.tar.gz"  ~% echo "${FILE%%.*}" example  ~% echo "${FILE%.*}" example.tar  ~% echo "${FILE#*.}" tar.gz  ~% echo "${FILE##*.}" gz 

For more details, see shell parameter expansion in the Bash manual.

vote vote

71

Usually you already know the extension, so you might wish to use:

basename filename .extension 

for example:

basename /path/to/dir/filename.txt .txt 

and we get

filename 
vote vote

69

You can use the magic of POSIX parameter expansion:

bash-3.2$ FILENAME=somefile.tar.gz bash-3.2$ echo "${FILENAME%%.*}" somefile bash-3.2$ echo "${FILENAME%.*}" somefile.tar 

There's a caveat in that if your filename was of the form ./somefile.tar.gz then echo ${FILENAME%%.*} would greedily remove the longest match to the . and you'd have the empty string.

(You can work around that with a temporary variable:

FULL_FILENAME=$FILENAME FILENAME=${FULL_FILENAME##*/} echo ${FILENAME%%.*} 

)


This site explains more.

${variable%pattern}   Trim the shortest match from the end ${variable##pattern}   Trim the longest match from the beginning ${variable%%pattern}   Trim the longest match from the end ${variable#pattern}   Trim the shortest match from the beginning 
vote vote

53

That doesn't seem to work if the file has no extension, or no filename. Here is what I'm using; it only uses builtins and handles more (but not all) pathological filenames.

#!/bin/bash for fullpath in "$@" do     filename="${fullpath##*/}"                      # Strip longest match of */ from start     dir="${fullpath:0:${#fullpath} - ${#filename}}" # Substring from 0 thru pos of filename     base="${filename%.[^.]*}"                       # Strip shortest match of . plus at least one non-dot char from end     ext="${filename:${#base} + 1}"                  # Substring from len of base thru end     if [[ -z "$base" && -n "$ext" ]]; then          # If we have an extension and no base, it's really the base         base=".$ext"         ext=""     fi      echo -e "$fullpath:\n\tdir  = \"$dir\"\n\tbase = \"$base\"\n\text  = \"$ext\"" done 

And here are some testcases:

 $ basename-and-extension.sh / /home/me/ /home/me/file /home/me/file.tar /home/me/file.tar.gz /home/me/.hidden /home/me/.hidden.tar /home/me/.. . /:     dir  = "/"     base = ""     ext  = "" /home/me/:     dir  = "/home/me/"     base = ""     ext  = "" /home/me/file:     dir  = "/home/me/"     base = "file"     ext  = "" /home/me/file.tar:     dir  = "/home/me/"     base = "file"     ext  = "tar" /home/me/file.tar.gz:     dir  = "/home/me/"     base = "file.tar"     ext  = "gz" /home/me/.hidden:     dir  = "/home/me/"     base = ".hidden"     ext  = "" /home/me/.hidden.tar:     dir  = "/home/me/"     base = ".hidden"     ext  = "tar" /home/me/..:     dir  = "/home/me/"     base = ".."     ext  = "" .:     dir  = ""     base = "."     ext  = "" 

Top 3 video Explaining string - Extract filename and extension in Bash

Related QUESTION?