目录是否可写

时间:2013-04-03 06:20:13

标签: linux bash shell testing writable

任何人都可以告诉我为什么这总是说目录不可写,绝对是什么时候?

    $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

3 个答案:

答案 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"