С GNUdate
:
$ date +%FT%T.%3N%:z
2017-06-30T13:00:54.566+01:00
С bash
встроенными функциями самое близкое, что вы можете получить, это:
$ printf -v date '%(%FT%T%z)T' -1
$ printf '%s\n' "${date%??}:${date: -2}"
2017-06-30T13:00:54+01:00
как bash
не поддерживает точность до доли секунды.
С последними версиямиzsh
:
$ zmodload zsh/datetime
$ strftime -s date '%FT%T.%3.%z'
$ printf '%s\n' $date[1,-3]:$date[-2,-1]
2017-06-30T13:00:54.566+01:00
rsync
выполняет эту работу. Временный файл O_EXCL
создается по умолчанию (отключен только в том случае, если вы используете --inplace
), а затем renamed
поверх целевого файла. Используйте --ignore-existing
, чтобы не перезаписывать B, если он существует.
На практике у меня никогда не возникало проблем с этим при монтировании ext4, zfs или даже NFS.
Вы можете написать для этого программу.
Используйте open(O_CREAT|O_RDWD)
, чтобы открыть целевой файл, прочитать все байты и метаданные, чтобы проверить, является ли целевой файл полным, если нет, есть две возможности,
Неполная запись
Другой процесс выполняет ту же программу.
Попытка установить блокировку описания открытого файла для целевого файла.
Сбой означает наличие параллельного процесса, текущий процесс должен существовать.
Успех означает, что последняя запись завершилась со сбоем, вы должны начать сначала или попытаться исправить это, записав в файл.
Также обратите внимание, что вам лучше fsync()
после записи в целевой файл, прежде чем закрыть файл и снять блокировку, иначе другой процесс может прочитать не -, а -данные на диске -.
https://www.gnu.org/software/libc/manual/html_node/Open-File-Description-Locks.html
Это важно, чтобы помочь вам отличить параллельно работающую программу от последней аварийно завершенной операции.
Вы получите правильный результат, выполнив cp
вместе с mv
. Это либо заменит «B» новой копией «A», либо оставит «B» таким, каким он был раньше.
cp A B.tmp && mv B.tmp B
обновление для соответствия существующимB
:
cp A B.tmp && if [ ! -e B ]; then mv B.tmp B; else rm B.tmp; fi
Это не 100% атомарность, но близко к этому. Существует состояние гонки, когда две из этих вещей работают, обе одновременно входят в тест if
, обе видят, что B
не существует, затем обе выполняют mv
.
Я думаю, Rsync — подходящий инструмент.
Вы должны использовать rsync -Pahn --контрольная сумма /path/from/source/destination/path
Однако будьте осторожны, файлы у вас очень большие...