检查当前用户是否有写权限的命令

检查当前用户是否有写权限的命令

我必须创建一个脚本来检查当前用户是否对文件具有写权限。如果没有,则会出现错误。

我写了这个:

if [namei -m /path/to/textfile.txt | grep w]; then 
  echo "message"

但我似乎遇到了语法错误。

答案1

让我们解决代码中的问题。正如 dessert 中提到的一条评论,第一个问题是命令的语法[。我们需要在[和 参数之间添加空格,因为 shell 使用空格来分隔字段,并认为这[namei就是您要运行的命令。

我将file在我的示例中使用主目录中的一个名为 的文件,我知道我对该文件有写入权限。我已将您的代码放在一行上,以便于交互测试。它将以与 后有换行符相同的方式工作then

$ if [namei -m playground | grep w]; then echo "writeable"
No command '[namei' found, did you mean:
 Command 'namei' from package 'util-linux' (main)
[namei: command not found

[让我们修复和周围的空格]

$ if [ namei -m playground | grep w ]; then echo "writeable"
>

现在我得到一个提示,让我输入一些东西,一个>。提示告诉我,shell 正在等待我输入一些东西。 的语法最简单的形式if

if condition; then command; fi

因此 shell 正在等待fi。如果我在提示符下输入它,我会得到以下内容:

$ if [ namei -m file | grep w ]; then echo "writeable"
> fi
bash: [: missing `]'
grep: ]: No such file or directory

看起来管道|在这里引起了问题,因为[找不到它的最后一个参数,并grep认为它的最后一个参数是]。由于[(或者我们在这里使用的那个)是 shell 内置的,我们应该能够使用以下方法获取有关它的一些信息help

$ help [
[: [ arg... ]
    Evaluate conditional expression.

    This is a synonym for the "test" builtin, but the last argument must
    be a literal `]', to match the opening `['.

我们不能在命令参数中间使用管道。在其他情况下,我们可以通过将它们括在 中来将命令放入子 shell 中,但这在(和)( )中是语法错误。[test

这里真正的问题是,我们试图传递给命令的东西[不是它可以评估为真或假的东西。如果你试图传递给的参数test是一个命令,test那么不会像你期望的那样使用该命令的退出状态。你可以传递输出命令的[使用命令替换,但这不是您或您的代码想要做的。

我认为您的代码试图做的是检查在 的输出中grep是否找到了。我们根本不需要该命令。wnamei -m somefiletest

$ help if
if: if COMMANDS; then COMMANDS; [ elif COMMANDS; then COMMANDS; ]... [ else COMMANDS; ] fi
    Execute commands based on conditional.

   The `if COMMANDS' list is executed.  If its exit status is zero, then the
   `then COMMANDS' list is executed.  Otherwise, each `elif COMMANDS' list is
   executed in turn, and if its exit status is zero, the corresponding
   `then COMMANDS' list is executed and the if command completes.  Otherwise,
   the `else COMMANDS' list is executed, if present.  The exit status of the
   entire construct is the exit status of the last command executed, or zero
   if no condition tested true.

因此,如果我们只对命令是否成功感兴趣,我们可以将命令作为条件if

$ if namei -m file | grep w; then echo "writeable"; fi
 -rw-rw-r-- file
writeable

您甚至可以使用-q它来抑制输出grep并仅收集其退出状态(如果找到匹配则表示成功):

$ if namei -m file | grep  -q w; then echo "writeable"; fi
writeable

但这不是测试文件是否可以被写入的好方法。让我们尝试另一个测试文件:

$ touch file_with_w
$ chmod 444 file_with_w
$ stat -c %A file_with_w 
-r--r--r--
$ if namei -m file_with_w | grep  -q w; then echo "writeable"; fi
writeable

namei -m如果我们解析名称中带有的文件的输出w,则此方法将使其看起来是可写的,即使它对所有人而言都是只读的。

解析命令的输出有时是获取所需信息的正确方法。但通常有更好的方法,以该命令的选项形式,或具有类似目的的其他命令。

让我们回到testaka[命令,看看它是否有任何有用的选项。您可以输入help test,或者有关更多详细信息,请阅读条件表达式部分Bash 手册

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

啊哈!该test命令正是我们想要的,正如回答中提到的那样检查文件是否可读可写

$ if [ -w file ]; then echo "writeable"; fi
writeable
$ if [ -w file_with_w ]; then echo "writeable"; fi
$ 

这是正确的 :)

但是您提到,如果文件不可写,您希望命令输出错误消息,而不是输出可写的声明。为此,我们需要一个else语句

$ if [ -w file_with_w ]; then echo "writeable"; else echo "not writeable"; fi
not writeable

作为脚本,您可以像这样编写该命令:

#!/bin/bash

if [ -w "$1" ]; then
   echo "writeable"
else
   echo "not writeable"
fi

然后你可以给它执行权限(替换script为实际的文件名)

chmod u+x script

并使用您想要测试的文件作为其参数来运行它(在脚本中引用$1):

$ ./script file
writeable
$ ./script file_with_w
not writeable

如果你仅有的想要在文件不可写入时收到错误消息,而在文件可写入时不输出任何内容,您可以否定测试条件,而不是编写 else:

$ if [ ! -w file_with_w ]; then echo "not writeable"; fi
not writeable

正如 Panther 所提到的一条评论,您可能还想使用变量$USER,该变量应扩展为运行 shell 的用户的名称。这样您就可以制作更令人印象深刻的错误消息:

$ if [ ! -w file_with_w ]; then echo "file is not writeable by $USER"; fi
file is not writeable by zanna

对于简单的test命令,您还可以使用[andtest[[without if,并使用 shell 运算符进行逻辑运算:

$ [ -w file_with_w ] || echo "not writeable"
not writeable

||是 shell 的逻辑或。这意味着如果前一个命令失败,则执行下一个命令

shell 的逻辑 AND 是&&

$ [ ! -w file_with_w ] && echo "not writeable"
not writeable

&&方法如果前一个命令成功,则执行下一个命令

所有这些都有效,因为该test命令提供了一个有用的退出状态,如下所述help test

Exit Status:
Returns success if EXPR evaluates to true; fails if EXPR evaluates to
false or an invalid argument is given.

相关内容