#! /bin/bash
shopt -s extglob

# POSIX dirname(1) without fork/exec.
#
# "Step N" below refers to the steps in the POSIX specification for dirname:
#    http://www.opengroup.org/onlinepubs/009695399/utilities/dirname.html
dirname () {
	# // is not treated specially by this implementation, so steps
	# 1 and 6 are ignored.

	# Ignore a first argument of '--'
	[[ $1 = -- ]] && shift

	if [[ $# -lt 1 ]]; then
		printf "%s: missing operand\n" "dirname" >&2
		return 1
	elif [[ $# -gt 1 ]]; then
		printf "%s: extra operand '%s'\n" "dirname" "$2" >&2
	fi

	# Handle empty string immediately.  The next step converts all-slash
	# strings to the empty string, but we need to be able to distinguish
	# between the two.
	if [[ ! "$1" ]]; then
		echo .
		return
	fi

	# Remove trailing slashes (step 3).  If the string was all slashes,
	# this gives us "" and our ${fn:-/} yields /.  Thus steps 1 and 2 are
	# handled as well.
	local fn=${1%%+(/)}

	if [[ "$fn" = +([!/]) ]]; then
		# No slashes, and the string hadn't been all-slashes.  It's
		# in the current directory (step 4).
		fn=.
	else
		# Remove trailing non-slashes and the slashes that precede them
		# (steps 5, 7).
		fn=${fn%%+(/)*([!/])}
	fi
	# convert empty string to "/" (step 8).
	printf "%s\n" "${fn:-/}"
}


dirname "$@"
