Bash: создайте файл, если он не существует, в противном случае проверьте, доступен ли он для записи - PullRequest
24 голосов
/ 22 декабря 2010

У меня есть программа bash, которая будет писать в выходной файл.Этот файл может существовать или не существовать, но скрипт должен проверять разрешения и рано выходить из строя.Я не могу найти элегантный способ сделать это.Вот что я попробовал.

set +e
touch $file
set -e

if [ $? -ne 0 ]; then exit;fi

Я оставляю set -e включенным для этого скрипта, чтобы он не работал, если в какой-либо строке возникнет ошибка.Есть ли более простой способ сделать приведенный выше скрипт?

Ответы [ 5 ]

32 голосов
/ 23 декабря 2010

Зачем все усложнять?

file=exists_and_writeable

if [ ! -e "$file" ] ; then
    touch "$file"
fi

if [ ! -w "$file" ] ; then
    echo cannot write to $file
    exit 1
fi

Или, точнее,

( [ -e "$file" ] || touch "$file" ) && [ ! -w "$file" ] && echo cannot write to $file && exit 1
23 голосов
/ 22 декабря 2010

Вместо проверки $? в другой строке, проверьте возвращаемое значение сразу, как это:

touch file || exit

Пока ваш umask не ограничивает установленный бит записи, вы можете просто положиться на возвращаемое значение touch

3 голосов
/ 23 декабря 2010

Почему скрипт должен рано выходить из строя?Разделив доступный для записи тест и файл open (), вы вводите условие гонки.Вместо этого, почему бы не попробовать открыть (усечь / добавить) файл для записи и устранить ошибку, если она возникает?Что-то вроде:

$ echo foo > output.txt
$ if [ $? -ne 0 ]; then die("Couldn't echo foo")

Как уже упоминалось, опция «noclobber» может быть полезна, если вы хотите избежать перезаписи существующих файлов.

3 голосов
/ 22 декабря 2010

Вы можете использовать -w, чтобы проверить, доступен ли файл для записи (найдите его на справочной странице bash).

if [[ ! -w $file ]]; then exit; fi
2 голосов
/ 23 декабря 2010

Открыть файл для записи. В оболочке это делается с помощью перенаправления вывода. Вы можете перенаправить стандартный вывод оболочки, поместив перенаправление на встроенный exec без аргументов.

set -e
exec >shell.out  # exit if shell.out can't be opened
echo "This will appear in shell.out"

Убедитесь, что вы не установили опцию noclobber (которая полезна в интерактивном режиме, но часто не используется в сценариях). Используйте >, если вы хотите обрезать файл, если он существует, и >>, если вы хотите добавить вместо него.

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

Если вы хотите, чтобы только некоторые команды записывали в файл, откройте его в другом дескрипторе, а затем перенаправьте при необходимости.

set -e
exec 3>foo.out
echo "This will appear on the standard output"
echo >&3 "This will appear in foo.out"
echo "This will appear both on standard output and in foo.out" | tee /dev/fd/3

(/dev/fd не поддерживается везде; он доступен по крайней мере в Linux, * BSD, Solaris и Cygwin.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...