Ответ 1
Вместо проверки $?
в другой строке немедленно проверьте возвращаемое значение следующим образом:
touch file || exit
Пока ваш umask
не ограничивает установку бита записи, вы можете просто положиться на возвращаемое значение touch
У меня есть программа bash, которая будет записывать в выходной файл. Этот файл может существовать или не существовать, но script должен проверять разрешения и отказываться раньше. Я не могу найти элегантный способ сделать это. Вот что я пробовал.
set +e touch $file set -e if [ $? -ne 0 ]; then exit;fi
Я поддерживаю set -e
для этого script, поэтому он терпит неудачу, если в любой строке есть ошибка. Есть ли более простой способ сделать выше script?
Вместо проверки $?
в другой строке немедленно проверьте возвращаемое значение следующим образом:
touch file || exit
Пока ваш umask
не ограничивает установку бита записи, вы можете просто положиться на возвращаемое значение touch
Зачем усложнять?
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
Почему сервер script не работает раньше? Разделив записываемый тест и файл open(), вы вводите условие гонки. Вместо этого, почему бы не попытаться открыть (усекать/добавить) файл для записи и справиться с ошибкой, если это произойдет? Что-то вроде:
$ echo foo > output.txt
$ if [ $? -ne 0 ]; then die("Couldn't echo foo")
Как упоминают другие, опция "noclobber" может быть полезна, если вы хотите избежать перезаписи существующих файлов.
Вы можете использовать -w
, чтобы проверить, доступен ли файл для записи (найдите его на странице bash).
if [[ ! -w $file ]]; then exit; fi
Откройте файл для записи. В оболочке это делается с перенаправлением вывода. Вы можете перенаправить стандартный вывод оболочки, поместив перенаправление на встроенный 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.)