我必须创建一个脚本来检查当前用户是否对文件具有写权限。如果不是,则应出现错误。
我是这样写的:
if [namei -m /path/to/textfile.txt | grep w]; then
echo "message"
Run Code Online (Sandbox Code Playgroud)
但我似乎收到语法错误。
让我们解决您的代码问题。正如评论中提到的甜点,第一个问题是[
命令的语法。我们需要在[
和它的参数之间放置空格,因为 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
,这个方法会使它看起来是可写的,即使它对每个人都是只读的。
解析命令的输出有时是获取所需信息的正确方法。但是通常有更好的方法,以该命令的选项或具有类似目的的不同命令的形式。
让我们回到test
aka[
命令,看看它是否有任何有用的选项。您可以输入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)