Skip to content

Instantly share code, notes, and snippets.

@zach-klippenstein
Created March 14, 2010 01:07
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save zach-klippenstein/331685 to your computer and use it in GitHub Desktop.
Save zach-klippenstein/331685 to your computer and use it in GitHub Desktop.
Returns the path passed to it with the case of components modified to match the actual names. See the comment header for more details.
#!/bin/bash
#
# usage: caseglob [--rename] path
# Prints the path, with the basename corrected to the actual case of the file, if
# a match can be made.
#
# If --rename is specified, if an unambiguous match is found, it will be renamed to
# path and returned in the original case.
#
# If there are 0 or more than 1 matches, the original basename is printed.
# If any of the components of the path don't exist, they are globbed as well.
# If a match couldn't be made, the path printed is as similar to the argument
# as possible: any recursive matches that could be made are included, but
# any non-existent or multiple matches are printed as given.
#
# Return values: if a unambiguous match was made, returns 0, else 1.
#
# By: Zachary Klippenstein
# On: 13/03/2010
# If this is set to a non-empty string, if a match is found, it will
# be renamed to the argument's version.
rename=""
# Process arguments
while [ "$(echo "$1" | egrep '^--.')" ]; do
case "$1" in
--rename)
# Set to the name of the option so it can be passed when recursing
rename="--rename"
;;
esac
shift
done
origPath="$1"
origDir="$(dirname "$origPath")"
origBase="$(basename "$origPath")"
echo -e "`date`\nChecking for '$origPath'..." >>/tmp/caseglob.log
if [ -d "$origDir" ]; then
# Case-insensitive search for the actual filename
# NOTE: - fgrep searches for fixed strings, not regular expressions.
# - 'i' makes case-insensitive
# - 'o' only prints the part of the line that matches. This is important
# because if origBase is only part of a filename, without 'o' we'd get
# ALL the files that had origBase as part of their names.
# However, this might result in a name which doesn't actually exist, so
# we check for the existence of the file before returning successfully.
# - 'e' allows origBase to start with a dash ('-')
# - Even if there are no matches, grep will return a newline, so we must check
# for an empty string as well as line number.
actualBase="$(/bin/ls -1 "$origDir" | fgrep -ioe "$origBase")"
numMatches=$(echo "$actualBase" | wc -l)
# 3 cases: more than 1 file matched, no files matched, or exactly 1 file matched
# We'll treat the first 2 the same, and print the original path, but return an error.
# Found only 1 existing match (unambiguous)
if [ $numMatches -eq 1 -a "$actualBase" -a -e "$origDir/$actualBase" ]; then
# If rename was specified and cases are actually different, rename
if [ "$rename" -a "$actualBase" != "$origBase" ]; then
mv "$origDir/$actualBase" "$origDir/$origBase"
actualBase="$origBase"
fi
echo "$origDir/$actualBase"
exit 0
# Either 0 or >1 matches:
# - if 0, let caller handle non-existent file normally.
# - if >1,
# if actual case exists, use that.
# if none of the matches are exact, let caller handle non-existent file
else
echo "$origDir/$origBase"
exit 1
fi
# Containing directory not found, attempt recursion
else
# Recurse upwards to find actual name of containing directory
actualDir="$("$0" $rename "$origDir")"
# Directory was successfully found
if [ $? -eq 0 ]; then
# Recurse with actual directory name to find actual basename
actualPath="$("$0" $rename "$actualDir/$origBase")"
# Check that the actual path exists
if [ $? -eq 0 -a -e "$actualPath" ]; then
echo "$actualPath"
exit 0
# Found the real containing directory, but the actual file doesn't exist
else
echo "$actualDir/$origBase"
exit 1
fi
# Recursion failed to find the actual directory, exit with
# error and original path
else
echo "$origDir/$origBase"
exit 1
fi
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment