3

私はファイルを持っています~/cwd。このファイルの内容は次の 1 行です。

~/tmp

cdこの (~/tmp) ディレクトリにfo が必要です。私はしようとしています:

> cd `cat ~/cwd`

そして得た:

-bash: cd: ~/tmp: No such file or directory

RELATIVE パスが失敗したのはなぜですか? の内容~/cwdが絶対パスの場合、機能します。

4

4 に答える 4

5

相対パスの問題ではありません。これは、シェル評価モデルがパラメーター展開の前にチルダ展開を行うために発生します。eval を使用して評価プロセスの最初までスキップすると、セキュリティ バグが発生します。したがって、これを本当にサポートする必要がある場合 (そして、それは悪い考えだと私は強く主張します)、安全な実装 (getentコマンドが使用可能) は次のようになります。

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 _ _ _ _ _ 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%:}"
}

...これをファイルから安全に読み取るパスに使用するには:

printf '%s\n' "$(expandPath "$(<file)")"

evalまたは、慎重に使用するより単純なアプローチ:

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
}
于 2013-09-11T13:40:05.520 に答える
1

必要なしcat:

eval cd "$(<~/cwd)"
于 2013-09-11T11:59:55.053 に答える