I want to get the filename (without extension) and the extension separately.
The best solution I found so far is:
NAME=`echo \"$FILE\" | cut -d\'.\'
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 = ""