该答案假定$1允许包含子目录。如果您对$1应该使用简单目录名的简单情况感兴趣,请参阅其他答案之一。
双引号中的通配符不展开。由于$1用双引号引起来,所以通配符不是问题。
无论../和符号链接可以掩盖真正的文件的位置。下面显示的是一些测试,用于确定文件是否确实在(而不只是在表面上)在所需路径下。
较新的系统:使用 realpath
至于确定文件是否确实在文件中 /home/charlesingalls/,可以使用realpath:
realpath --relative-base=/home/charlesingalls/ "/home/charlesingalls/$1" | grep -q '^/' && exit 1
exit 1如果由指定的文件不在$1目录下的任何位置,则以上命令将运行/home/charlesingalls/。 realpath规范化了整个路径,消除了符号链接和../。
realpath 是GNU coreutils的一部分,应在任何Linux系统上可用。
realpath需要GNU coreutils 8.15(2012年1月)或更高版本。
例子
为了演示realpath如何../确定文件的实际位置(例如,-q省略了grep 的选项,以便可以看到grep的实际输出):
$ touch /tmp/test
$ realpath --relative-base=$HOME "$HOME/../../tmp/test" | grep '^/' && echo FAIL
/tmp/test
FAIL
为了演示它如何遵循符号链接:
$ ln -s /tmp/test ~/test
$ realpath --relative-base=$HOME "$HOME/test" | grep '^/' && echo FAIL
/tmp/test
FAIL
较旧的系统:使用 readlink -e
readlink通过符号链接和也可以对路径进行音化../:
readlink -e "$HOME/test" | grep -q "^$HOME" || exit 1
使用相同的示例文件:
$ readlink -e "$HOME/../../tmp/test" | grep "$HOME" || echo FAIL
FAIL
$ readlink -e "$HOME/test" | grep "^$HOME" || echo FAIL
FAIL
除了可以在较旧的GNU系统readlink上使用之外,BSD 上还可以使用的版本。
/。不能在引号内解释通配符。