传递字符串值将无法找到该文件

时间:2016-05-25 01:55:58

标签: bash

我写了一个shell,它会尝试从文件路径收集一个文件到当前目录中,如果它存在:

collect_file() {
  fpath=$1
  echo $fpath
  if [ -e $fpath ]; then

    fname=`basename $fpath`
    `cp $1 $fname`
    retval=$?
    if [ $retval == 0 ]; then
      echo "Collect file '$fpath'"
    else
      echo "Error: fail to copy file '$fpath'"
    fi

  else
    echo "Error: file '$fpath' not found"
  fi  
}

现在,如果我传递一个空值~/.gitconfig,它将会成功,但是当我传递一个字符串值"~/.gitconfig"时,它将会失败。

collect_file ~/.gitconfig        # will succeed to copy the file
collect_file "~/.gitconfig"      # will fail

节目:

# results for bare value
/Users/Xaree/.gitconfig
Collect file '/Users/Xaree/.gitconfig'

# results for string value
~/.gitconfig
Error: file '~/.gitconfig' not found

为什么以及如何解决?

1 个答案:

答案 0 :(得分:1)

以下是指用户主目录中的文件:

~/.gitconfig

相反,以下内容是指名为~

的目录中的文件
"~/.gitconfig"
当shell执行代码扩展时,

~/被解释为主目录。当!未加引号时,shell仅执行代码扩展。如果引用该字符串,则~仅表示~,而不是其他任何内容。

实施例

注意只对以下三个陈述中的一个执行代码扩展

$ echo "~/.bashrc"
~/.bashrc
$ echo ~"/.bashrc"
~/.bashrc
$ echo ~/".bashrc"
/home/john1024/.bashrc

强制波浪扩展

由shell实现的Tilde扩展提供了许多特殊情况的特性。我们可以使用eval强制进行一般波浪扩展,但这会引入许多安全问题。但是,对于基本情况,我们可以安全地将变量中的~/替换为$HOME/,如下所示:

fpath="${fpath/~\//$HOME\/}"

上述问题是即使字符串不以~/开头,它也会替换第一次出现的~/。为避免这种情况,我们可以使用:

[ "${fpath#\~/}" != "$fpath" ] && fpath="${fpath/~\//$HOME\/}"

这将测试以确保字符串在进行替换之前以~/开头。