Команда, чтобы проверить, имеет ли текущий пользователь права на запись

3

Мне нужно создать скрипт, чтобы проверить, имеет ли текущий пользователь права на запись в файл. Если нет, должна появиться ошибка.

Я написал это:

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

Но я, кажется, получаю синтаксическую ошибку.

    
задан Diqn Raikov 27.11.2017 в 11:06
источник

1 ответ

5

Давайте рассмотрим проблемы с вашим кодом. Как десерт упоминается в комментарий , первой проблемой является синтаксис команды [ . Нам нужно поставить пробелы между [ и его аргументами, потому что оболочка использует пробелы для разделения полей и думает, что [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"
>

Теперь я получаю приглашение ввести что-то, > . В подсказке сообщается, что оболочка ждет меня, чтобы что-то ввести. Простейшей формой синтаксиса if является

if condition; then command; fi

, поэтому оболочка ожидает fi . Если я введу его в подсказку, я получу это:

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

Похоже, что проблема pipe | вызывает здесь проблемы, так как [ не может найти свой последний аргумент, а grep считает, что его последний аргумент равен ] . Поскольку [ (или тот, который мы здесь используем), является встроенной оболочкой, мы можем получить некоторую информацию об этом, используя 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 '['.

Мы не можем использовать канал в середине аргументов команды. В других ситуациях мы могли бы поместить команды в подоболочку, включив их в ( ) , но это синтаксическая ошибка в [test ).

Реальная проблема заключается в том, что то, что мы пытаемся передать команде [ , не может быть оценено как true или false. Если аргумент, который вы пытаетесь передать в test , является командой, test не использует статус выхода этой команды, как я думаю, вы ожидаете. Вы можете передать вывод команды в [ , используя подстановка команд , но это не то, что вы или ваш код хотите делать.

Я думаю, что ваш код пытается сделать, это проверить, что grep нашел w в выходе namei -m somefile . Для этого нам не нужна команда test .

$ 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 в его имени, этот метод заставит его отображаться, даже если он будет доступен только для всех.

Разбор вывода команд иногда является правильным способом получения требуемой информации. Но обычно есть лучший способ, в виде опции для этой команды, или другая команда с аналогичной целью.

Вернемся к команде test aka [ и посмотрим, есть ли у нее какие-либо полезные опции. Вы можете ввести 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 "" ]; then
   echo "writeable"
else
   echo "not writeable"
fi

Затем вы можете предоставить ему разрешение на выполнение (замените script на фактическое имя файла)

chmod u+x script

и запустите его с файлом, который вы хотите проверить в качестве его аргумента (ссылка на скрипт с ):

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

Если вы only хотите получить сообщение об ошибке, когда файл не записывается, и нет вывода, когда он есть, вы можете отменить условие теста, а не писать другое:

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

Как рассказала Пантера в a комментарий , вы также можете использовать переменную $USER , которая должна быть расширена до имени пользователя, запускающего оболочку. Таким образом, вы можете сделать более впечатляющее сообщение об ошибке:

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

Для простых команд test вы также можете использовать [ и test и [[ без if и использовать операторы оболочки для логики:

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

|| - логическое ИЛИ.Это означает , если предыдущая команда не удалась, затем выполните следующую команду

Логический логический код оболочки 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.
    
ответ дан Zanna 27.11.2017 в 17:19