2

谁能告诉我为什么总是说目录不可写,而绝对是不可写的?

    $dnam="/home/bryan/renametest/CD"

    # 目录是否可写
    错误=0
    如果 [ !-w $dnam]
    然后
        # 不可写。弹出错误并退出。
        echo "目录 $dnam 不可写"
        错误=1
    菲
4

3 回答 3

5

你需要双引号$dnam- 没有它们,它会被解释为两个单独的 shell 单词,“/home/bryan/renametest/C”和“D”,这会产生无效的测试表达式并因此失败。这应该有效:

if [ ! -w "$dnam" ]

@tink 的建议[[ ]]是进行此类测试的一种更简洁的方法,但仅适用于 bash(以及其他一些具有扩展语法的 shell)。您得到的事实[[: not found意味着您使用的是相当基本的 shell,而不是 bash。

于 2013-04-03T06:54:56.673 回答
0

我看到多个问题:

  • 您在变量中使用了一个空格。这不是非法的,但在组合行中,您使用变量 unscaped 并生成以下命令:

    if [ ! -w /home/bryan/renametest/C D ]
    

    这不是有效的语法。解决此问题的最简单方法是将行更改为

    if [ ! -w "$dnam" ]
    
  • 下一个问题更糟:在我的系统上,help test返回文本:

    -w FILE        True if the file is writable by you.
    

    这意味着,该命令不支持目录,而只支持文件。如果要检查目录是否可写,则必须使用不同的命令

于 2015-04-15T14:23:15.763 回答
0

正如其他人所说,$dnam变量需要双引号。原因如下:

[ ... ]是命令的别名test。如果你查看你的系统,你会看到一个名为/bin/[或者可能是/bin/usr/[. /bin/test在某些系统上,这是指向or的硬链接/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都是内置命令,但它们仍然是*still命令。这意味着 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对变量的插值等问题。而且,如果您不是非常小心,最终可能会出现错误。

更糟糕的是,有时[ ... ]可能会起作用,有时可能不起作用。如果您的目录名称不包含空格,它将按预期工作。想象一下,您正在编写一个程序,并且您对其进行测试并且一切正常,因为您尝试过的所有目录都没有空格。然后,有人使用您的程序,但在目录中有空间。大量的 shell 脚本错误是针对if语句中的此类问题。

这就是 Bash 引入[[ ... ]]测试的原因。[[不是命令,而是声明。这意味着外壳不会直接对结果进行插值。相反,参数被解析,然后进行任何插值。因此,这将起作用:

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"
于 2015-04-15T14:56:13.240 回答