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

Diq*_*kov 4 command-line bash

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

我是这样写的:

if [namei -m /path/to/textfile.txt | grep w]; then 
  echo "message"
Run Code Online (Sandbox Code Playgroud)

但我似乎收到语法错误。

Zan*_*nna 6

让我们解决您的代码问题。正如评论中提到的甜点,第一个问题是[命令的语法。我们需要在[和它的参数之间放置空格,因为 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
Run Code Online (Sandbox Code Playgroud)

让我们围绕解决空间[]

$ if [ namei -m playground | grep w ]; then echo "writeable"
>
Run Code Online (Sandbox Code Playgroud)

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

if condition; then command; fi
Run Code Online (Sandbox Code Playgroud)

所以 shell 正在等待fi. 如果我在提示符下输入它,我会得到这个:

$ if [ namei -m file | grep w ]; then echo "writeable"
> fi
bash: [: missing `]'
grep: ]: No such file or directory
Run Code Online (Sandbox Code Playgroud)

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

$ 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
Run Code Online (Sandbox Code Playgroud)

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

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

我想你的代码是试图做的是检查grep发现w的输出namei -m somefile。我们根本不需要这个test命令。

$ if [ namei -m playground | grep w ]; then echo "writeable"
>
Run Code Online (Sandbox Code Playgroud)

所以如果我们只关心命令是否成功,我们可以把命令作为条件if

$ if namei -m file | grep w; then echo "writeable"; fi
 -rw-rw-r-- file
writeable
Run Code Online (Sandbox Code Playgroud)

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

$ if namei -m file | grep  -q w; then echo "writeable"; fi
writeable
Run Code Online (Sandbox Code Playgroud)

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

$ 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
Run Code Online (Sandbox Code Playgroud)

如果我们解析namei -m一个文件名中包含 a 的文件的输出w,这个方法会使它看起来是可写的,即使它对每个人都是只读的。

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

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

if condition; then command; fi
Run Code Online (Sandbox Code Playgroud)

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

$ if [ -w file ]; then echo "writeable"; fi
writeable
$ if [ -w file_with_w ]; then echo "writeable"; fi
$ 
Run Code Online (Sandbox Code Playgroud)

这是正确的 :)

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

$ if [ -w file_with_w ]; then echo "writeable"; else echo "not writeable"; fi
not writeable
Run Code Online (Sandbox Code Playgroud)

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

#!/bin/bash

if [ -w "$1" ]; then
   echo "writeable"
else
   echo "not writeable"
fi
Run Code Online (Sandbox Code Playgroud)

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

chmod u+x script
Run Code Online (Sandbox Code Playgroud)

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

$ ./script file
writeable
$ ./script file_with_w
not writeable
Run Code Online (Sandbox Code Playgroud)

如果你希望在该文件是不可写,而当它没有输出,你可以否定,而不是写一个其他的测试条件,以得到一个错误信息:

$ if [ ! -w file_with_w ]; then echo "not writeable"; fi
not writeable
Run Code Online (Sandbox Code Playgroud)

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

$ if [ ! -w file_with_w ]; then echo "file is not writeable by $USER"; fi
file is not writeable by zanna
Run Code Online (Sandbox Code Playgroud)

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

$ [ -w file_with_w ] || echo "not writeable"
not writeable
Run Code Online (Sandbox Code Playgroud)

||是 shell 的逻辑 OR。意思是如果上一条命令失败,则执行下一条命令

shell 的逻辑 AND 是&&

$ [ ! -w file_with_w ] && echo "not writeable"
not writeable
Run Code Online (Sandbox Code Playgroud)

&&表示如果上一条命令成功,则执行下一条命令

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

$ if [ namei -m file | grep w ]; then echo "writeable"
> fi
bash: [: missing `]'
grep: ]: No such file or directory
Run Code Online (Sandbox Code Playgroud)