How to manually expand a special variable (ex: ~ tilde) in bash

前端 未结 15 2315
离开以前
离开以前 2020-11-22 09:34

I have a variable in my bash script whose value is something like this:

~/a/b/c

Note that it is unexpanded tilde. When I do ls -lt on this

15条回答
  •  春和景丽
    2020-11-22 09:54

    Plagarizing myself from a prior answer, to do this robustly without the security risks associated with eval:

    expandPath() {
      local path
      local -a pathElements resultPathElements
      IFS=':' read -r -a pathElements <<<"$1"
      : "${pathElements[@]}"
      for path in "${pathElements[@]}"; do
        : "$path"
        case $path in
          "~+"/*)
            path=$PWD/${path#"~+/"}
            ;;
          "~-"/*)
            path=$OLDPWD/${path#"~-/"}
            ;;
          "~"/*)
            path=$HOME/${path#"~/"}
            ;;
          "~"*)
            username=${path%%/*}
            username=${username#"~"}
            IFS=: read -r _ _ _ _ _ homedir _ < <(getent passwd "$username")
            if [[ $path = */* ]]; then
              path=${homedir}/${path#*/}
            else
              path=$homedir
            fi
            ;;
        esac
        resultPathElements+=( "$path" )
      done
      local result
      printf -v result '%s:' "${resultPathElements[@]}"
      printf '%s\n' "${result%:}"
    }
    

    ...used as...

    path=$(expandPath '~/hello')
    

    Alternately, a simpler approach that uses eval carefully:

    expandPath() {
      case $1 in
        ~[+-]*)
          local content content_q
          printf -v content_q '%q' "${1:2}"
          eval "content=${1:0:2}${content_q}"
          printf '%s\n' "$content"
          ;;
        ~*)
          local content content_q
          printf -v content_q '%q' "${1:1}"
          eval "content=~${content_q}"
          printf '%s\n' "$content"
          ;;
        *)
          printf '%s\n' "$1"
          ;;
      esac
    }
    

提交回复
热议问题