Я делаю следующее:
if [ -f $FILE ] ; then
echo "File exists"
fi
Но я хочу -f
быть нечувствительным к регистру. Таким образом, если ФАЙЛ /etc/somefile
, Я хочу, чтобы-f распознал /Etc/SomeFile
.
Я могу частично работать вокруг этого с шариком:
shopt -s nocaseglob
TARG='/etc/somefile'
MATCH=$TARG* #assume it returns only one match
if [[ -f $MATCH ]] ; then
echo "File exists"
fi
но нечувствительный к регистру globbing работает только над частью имени файла, не полным путем. Таким образом, это не будет работать, если TARG будет /Etc/somefile
.
Там какой-либо путь состоит в том, чтобы сделать это?
Проблема в том, что ваша файловая система - case- чувствительный. Файловая система предоставляет только два подходящих способа получить файл: либо вы указываете точное имя файла с учетом регистра и проверяете его существование таким образом, либо вы читаете все файлы в каталоге, а затем проверяете, соответствует ли каждый из них шаблону.
Другими словами, очень неэффективно проверять, существует ли нечувствительная к регистру версия файла в чувствительной к регистру файловой системе. Оболочка может сделать это за вас, но внутри она читает все содержимое каталога и проверяет каждое на соответствие шаблону.
Учитывая все это, это работает:
if [[ -n `find /etc -maxdepth 1 -iname passwd` ]];
then echo "Found";
fi
НО если вы не хотите искать все, начиная с '/' и ниже, вы должны проверять компонент пути индивидуально. Нет никакого способа обойти это; вы не можете волшебным образом проверить весь путь на совпадения без учета регистра в файловой системе с учетом регистра!
не знает, как использовать только оценки оболочки. но grep может быть нечувствительным к регистру, поэтому сценарий, который вызывает grep, find и wc, может удовлетворить ваши требования.
вы можете использовать опцию nocasematch
shopt -s nocasematch
for file in *
do
case "$file" in
"/etc/passWd" ) echo $file;;
esac
done
Это очень трудно сделать в общем случае, если файловая система не чувствительна к регистру. В основном вам придется перебирать все каталоги-предки по отдельности. Вот отправная точка в Python:
import os
def exists_nocase(path):
if os.path.exists(path):
return True
path = os.path.normpath(os.path.realpath(os.path.abspath(unicode(path)))).upper()
parts = path.split(os.sep)
path = unicode(os.path.join(unicode(os.path.splitdrive(path)[0]), os.sep))
for name in parts:
if not name:
continue
# this is a naive and insane way to do case-insensitive string comparisons:
entries = dict((entry.upper(), entry) for entry in os.listdir(path))
if name in entries:
path = os.path.join(path, entries[name])
else:
return False
return True
print exists_nocase("/ETC/ANYTHING")
print exists_nocase("/ETC/PASSWD")
cd /etc
# using FreeBSD find
find -x -L "$(pwd)" -maxdepth 1 -type f -iregex "/EtC/[^\/]*" -iname paSSwd
А вот отправная точка с использованием Bash:
# fci -- check if file_case_insensitive exists
# (on a case sensitive file system; complete file paths only!)
function fci() {
declare IFS checkdirs countslashes dirpath dirs dirstmp filepath fulldirpaths i name ndirs result resulttmp
[[ -f "$1" ]] && { return 0; }
[[ "${1:0:1}" != '/' ]] && { echo "No absolute file path given: ${1}" 2>&1; return 1; }
[[ "$1" == '/' ]] && { return 1; }
filepath="$1"
filepath="${filepath%"${filepath##*[!/]}"}" # remove trailing slashes, if any
dirpath="${filepath%/*}"
name="${filepath##*/}"
IFS='/'
dirs=( ${dirpath} )
if [[ ${#dirs[@]} -eq 0 ]]; then
fulldirpaths=( '/' )
ndirs=1
else
IFS=""
dirs=( ${dirs[@]} )
ndirs=${#dirs[@]}
for ((i=0; i < ${ndirs}; i++)); do
if [[ $i -eq 0 ]]; then
checkdirs=( '/' )
else
checkdirs=( "${dirstmp[@]}" )
fi
IFS=$'\777'
dirstmp=( $( find -x -L "${checkdirs[@]}" -mindepth 1 -maxdepth 1 -type d -iname "${dirs[i]}" -print0 2>/dev/null | tr '\0' '\777' ) )
IFS=""
fulldirpaths=( ${fulldirpaths[@]} ${dirstmp[@]} )
done
fi
printf "fulldirpaths: %s\n" "${fulldirpaths[@]}" | nl
for ((i=0; i < ${#fulldirpaths[@]}; i++)); do
countslashes="${fulldirpaths[i]//[^\/]/}"
[[ ${#countslashes} -ne ${ndirs} ]] && continue
IFS=$'\777'
resulttmp=( $( find -x -L "${fulldirpaths[i]}" -mindepth 1 -maxdepth 1 -type f -iname "${name}" -print0 2>/dev/null | tr '\0' '\777' ) )
IFS=""
result=( ${result[@]} ${resulttmp[@]} )
done
IFS=""
result=( ${result[@]} )
printf "result: %s\n" "${result[@]}" | nl
if [[ ${#result[@]} -eq 0 ]]; then
return 1
else
return 0
fi
}
FILE='/eTC/paSSwD'
if fci "${FILE}" ; then
echo "File (case insensitive) exists: ${FILE}"
else
echo "File (case insensitive) does NOT exist: ${FILE}"
fi