任何人都可以告诉我为什么这总是说目录不可写,绝对是什么时候?
$dnam="/home/bryan/renametest/C D" # Is the directory writable err=0 if [ ! -w $dnam ] then # Not writable. Pop the error and exit. echo "Directory $dnam is not writable" err=1 fi
答案 0 :(得分:5)
你需要在$dnam
附近使用双引号 - 没有它们,它被解释为两个单独的shell单词,“/ home / bryan / renametest / C”和“D”,这会产生无效的测试表达式,因此失败。这应该有效:
if [ ! -w "$dnam" ]
@tink的[[ ]]
建议是一种更简洁的方式来进行这样的测试,但只能在bash中使用(以及其他一些扩展语法的shell)。你得到[[: not found
的事实意味着你使用的是一个相当基本的shell,而不是bash。
答案 1 :(得分:0)
我看到了多个问题:
您在变量中使用了空格。这不是非法的,但在组合行中,您使用未转义的变量并生成以下命令:
if [ ! -w /home/bryan/renametest/C D ]
这不是有效的语法。解决此问题的最简单方法是将行更改为
if [ ! -w "$dnam" ]
下一个问题更严重:在我的系统上,help test
返回文字:
-w FILE True if the file is writable by you.
这意味着,该命令不支持目录,只支持文件。如果要检查目录是否可写,则必须使用其他命令
答案 2 :(得分:0)
正如其他人所说,$dnam
变量需要双引号。这就是原因:
[ ... ]
是test
命令的别名。如果您查看系统,则会看到名为/bin/[
或/bin/usr/[
的文件。在某些系统上,这是指向/bin/test
或/bin/usr/test
的硬链接。 if
语句执行 if
之后的内容,如果该命令返回零退出状态,if
语句将执行then
语句条款。否则,如果存在else
子句,则会执行。
为了允许布尔测试,Unix包含了test
命令,所以你可以这样做:
if test -d "$directory"
then
echo "Directory $directory exists!"
fi
后来,/bin/[
被添加为语法糖。这与上面的相同:
if [ -d "$directory" ]
then
echo "Directory $directory exists!"
fi
现在,[
和test
都是内置命令,但它们是 *仍然命令。这意味着shell会插入命令然后执行它。
尝试执行以下操作:
$ set -xv # Turns on shell debugging
$ dnam="/home/bryan/renametest/C D"
dnam="/home/bryan/renametest/C D"
+ dnam='/home/bryan/renametest/C D'
$ test -d $dnam
test -d $dnam
+ test -d /home/bryan/renametest/C D
$ echo $?
echo $?
+ echo 1
1
$ test -d "$dnam" # Now with quotes
test -d $dnam
+ test -d "/home/bryan/renametest/C D"
$ echo $?
echo $?
+ echo 0
0
$ set +xv # Turn off the debuggin
每个命令都会回显两次。第一次写入,第二次插入行后。作为插值的一部分,shell在白色空间上分割参数。如您所见,test
命令正在测试/home/bryan/renamtest/C
的存在,它不存在,因此不可写。我真的很惊讶test
命令没有打印错误信息,因为你传递了一个额外的参数。
在第二次尝试中,您添加了引号。这些引号阻止了shell在空间上拆分参数,并将目录名称保留为单个参数。
由于[ ... ]
是一个命令,你必须考虑shell的变量插值和其他问题。并且,如果您不是非常小心,最终可能会出错。
更糟糕的是,有时[ ... ]
可能有效,有时可能无效。如果您的目录名称不包含空格,它将按预期工作。想象一下,你正在编写一个程序,并且你测试它并且一切正常,因为你尝试过的所有目录都没有空格。然后,有人使用您的程序,但在目录中有一个空格。在if
语句中,大量的shell脚本错误都与此类问题有关。
这就是Bash引入[[ ... ]]
测试的原因。 [[
不是命令而是声明。这意味着shell不会直接插入结果。相反,解析参数,然后进行任何插值。因此,这将起作用:
dnam="/home/bryan/renametest/C D" # No "$" in front of the variable!
# Is the directory writable
if [[ ! -w $dnam ]] # No quotation marks needed!
then
# Not writable. Pop the error and exit.
echo "Directory $dnam is not writable"
err=1
fi
使用[[ ... ]]
测试而不是[ ... ]
测试几乎总是更好,所以请继续养成习惯。
还有一个小错误,你有:
$dnam="/home/bryan/renametest/C D"
这由shell进行插值,因此设置的变量就是$dnam
恰好是的值。如果$dnam
碰巧等于" foo",那么你会这样做:
foo="/home/bryan/renametest/C D"
不是你想要的。
您希望在设置变量时关闭$
:
dnam="/home/bryan/renametest/C D"