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

  • 本文关键字:文件 字符串 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

为什么以及如何修复?

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

~/.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/}"

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

相关内容

  • 没有找到相关文章

最新更新