SyntaxError: unexpected EOF while parsing
означает, что конец вашего исходного кода был достигнут до того, как все кодовые блоки были завершены. Блок кода начинается с выражения типа for i in range(100):
и требует, по крайней мере, одной строки, которая содержит код, который должен быть в нем.
Кажется, что вы выполняли вашу программу по строкам в консоли ipython. Это работает для отдельных операторов типа a = 3
, но не для блоков кода, например для циклов. См. Следующий пример:
In [1]: for i in range(100):
File "<ipython-input-1-ece1e5c2587f>", line 1
for i in range(100):
^
SyntaxError: unexpected EOF while parsing
Чтобы избежать этой ошибки, вы должны ввести весь блок кода как один вход:
In [2]: for i in range(5):
...: print(i, end=', ')
0, 1, 2, 3, 4,
Решение 100% чистого bash:
set -o noclobber
{ > file ; } &> /dev/null
Эта команда создает файл с именем file
, если нет файла с именем file
. Если есть файл с именем file
, то ничего не делайте (но возвращайте ненулевой код возврата).
Прыжки по команде touch
:
file
уже существует или невозможно создать file
; если file
не существует и был создан. Минусы:
noclobber
(но все в порядке скрипт, если вы осторожны с перенаправлением или после этого отмените его). Я предполагаю, что это решение действительно является аналогом bash системного вызова open
с O_CREAT | O_EXCL
.
Вы можете создать его под произвольно созданным именем, а затем переименовать (mv -n random desired
) на место с нужным именем. Переименование не будет выполнено, если файл уже существует.
Нравится это:
#!/bin/bash
touch randomFileName
mv -n randomFileName lockFile
if [ -e randomFileName ] ; then
echo "Failed to acquired lock"
else
echo "Acquired lock"
fi
touch
- это команда, которую вы ищете. Он обновляет временные метки предоставленного файла, если файл существует или создает его, если он этого не делает.
Вот функция bash с использованием трюка mv -n
:
function mkatomic() {
f="$(mktemp)"
mv -n "$f" "$1"
if [ -e "$f" ]; then
rm "$f"
echo "ERROR: file exists:" "$1" >&2
return 1
fi
}
Примеры:
$ mkatomic foo
$ wc -c foo
0 foo
$ mkatomic foo
ERROR: file exists: foo
Чтобы быть ясным, гарантировать, что файл будет создан только в том случае, если он не существует, это не то же самое, что атомарность. Операция является атомной тогда и только тогда, когда два или несколько отдельных потоков пытаются сделать одно и то же в одно и то же время, точно один будет успешным, а все остальные потерпят неудачу.
Лучший способ, которым я знаю создайте файл атомарно в сценарии оболочки, следуя этому шаблону (и это не идеально):
В частности, touch
не является атомарным, так как он создаст файл, если его там нет, или просто обновить метку времени. Возможно, вы сможете играть в игры с разными отметками времени, но чтение и синтаксический анализ временной метки, чтобы увидеть, выиграл ли вы гонку, сложнее, чем указано выше. mkdir
может быть атомарным, но вам нужно будет проверить код возврата, потому что в противном случае вы можете только сказать, что «да, каталог был создан, но я не знаю, какой поток выиграл». Если вы находитесь в файловой системе, которая не поддерживает жесткие ссылки, вам, возможно, придется согласиться на менее идеальное решение.
open()
с O_EXCL
непосредственно из сценария bash
, что и было в исходном вопросе.
– twalberg
31 May 2018 в 18:44
(set -o noclobber;>file) &>/dev/null
делает то же самое, но не влияет на параметрnoclobber
в текущей оболочке. – Rich Remer 22 November 2017 в 08:42