3

我有一个文件,说:~/cwd. 这个文件的内容是一行:

~/tmp

我想要cd这个(〜/ tmp)目录。我正在努力:

> cd `cat ~/cwd`

并得到:

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

为什么相对路径失败?当 的内容~/cwd是绝对路径时-它可以工作。

4

4 回答 4

5

相对路径不是问题——发生这种情况是因为 shell 评估模型在参数扩展之前进行波浪号扩展。使用 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 回答
2

尝试这个:

eval cd `cat ~/cwd`

'~' 需要由 shell 扩展。eval 使命令通过 shell 的命令处理运行,其中包括 '~' 扩展。

于 2013-09-11T11:47:23.940 回答
2

使用eval

eval cd $(cat file)

否则 shell 将无法解释~.

于 2013-09-11T11:47:08.950 回答
1

无需cat

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