代码之家  ›  专栏  ›  技术社区  ›  Paul Richter

在bash中,文件运算符(-f)是否可以不区分大小写?

  •  7
  • Paul Richter  · 技术社区  · 14 年前

    我正在做以下工作:

    if [ -f $FILE ] ; then
        echo "File exists"
    fi
    

    但是我想要 -f 不区分大小写。也就是说,如果文件 /etc/somefile ,我要-f来识别 /Etc/SomeFile

    我可以用glob部分解决这个问题:

    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

    有什么办法吗?

    6 回复  |  直到 12 年前
        1
  •  10
  •   Pablo Bianchi    5 年前

    文件系统

    考虑到所有这些,这是可行的:

    if [[ -n $(find /etc -maxdepth 1 -iname passwd) ]]; then
      echo "Found";
    fi
    

    但是,除非要搜索从“/”开始的所有内容,否则必须逐个检查路径的组件。这是没有办法的;在一个区分大小写的文件系统上,你不能神奇地检查整个路径是否有不区分大小写的匹配!

        2
  •  1
  •   Jokester    14 年前

    不知道如何只使用shell计算。 但是grep可以不区分大小写,因此调用grep、find和wc的脚本可以满足您的需求。

        3
  •  0
  •   ghostdog74    14 年前

    您可以使用nocasematch选项

    shopt -s nocasematch
    for file in *
    do
      case "$file" in
       "/etc/passWd" ) echo $file;;
      esac
    done 
    
        4
  •  0
  •   Philipp    14 年前

    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")
    
        5
  •  0
  •   carlo    14 年前
    cd /etc
    # using FreeBSD find
    find -x -L "$(pwd)" -maxdepth 1 -type f -iregex "/EtC/[^\/]*" -iname paSSwd 
    
        6
  •  0
  •   juan    14 年前

    #  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