Bash One-Liner, um eine Datei atomar zu erstellen, wenn sie nicht existiert

9

Ich möchte einen Bash-Einzeiler, der eine Datei atomar erstellt, wenn sie nicht vorhanden ist. Das bedeutet im Wesentlichen "Wenn eine Datei nicht vorhanden ist, erstellen Sie sie", aber stellen Sie sicher, dass es niemand anderem gelingt, die Datei auf kleinem Raum zwischen dem Ausführen des if und dem Erstellen der Datei zu erstellen.

Ram Rachum
quelle
Entschuldigung, ich habe "atomar" als "automatisch" gelesen. Ich habe meine Antwort gelöscht.
Aaron Copley
3
Hast du das gesehen; Atomic Create-Datei, wenn nicht aus Bash-Skript existiert ?
Aaron Copley

Antworten:

6

Eine Antwort aus verschiedenen Kommentaren und Links zu [SO] stehlen . Es scheint, dass es eine POSIX-kompatible Methode gibt , die nicht die mkdirin meiner ursprünglichen Antwort unten erwähnte beinhaltet

set -o noclobber # or set -C
{ > file ; } &> /dev/null

Diese Umleitung zur Datei gibt 0 zurück oder schlägt fehl und gibt einen Wert ungleich Null zurück, wenn die Datei bereits vorhanden ist.


Ursprüngliche Antwort

Sie müssen verwenden mkdir- das ist atomar, entweder wird das Verzeichnis erstellt und Sie können fortfahren oder es wird nicht erstellt, sodass Sie geeignete Maßnahmen ergreifen.

Natürlich wird mkdirkeine Datei erstellt, aber sobald Sie wissen, dass Sie exklusiven Zugriff auf das Verzeichnis haben, können Sie die gewünschte Datei erstellen.

Was einen Einzeiler betrifft, überlasse ich das Ihnen. Persönlich würde ich es über ein paar Zeilen schreiben, da das wartbarer ist.

user9517
quelle
Aber noclobber von stackoverflow.com/q/13828544/1207760 ist mehr, was OP will.
Gesetz29
Noclobber ist im Allgemeinen eine gute Antwort. Aber es funktioniert nicht für ksh88.
jrw32982 unterstützt Monica
1
@ JohnWiersba, aber die Frage ist über Bash.
womble
@womble ja, aber die Antwort erwähnt POSIX, was jemand bedeuten könnte, dass die Antwort für andere Shells gilt. Ksh88 ist auf einigen Servern immer noch die Standard-Shell.
jrw32982 unterstützt Monica
0

Ist es eine Datei oder ein Verzeichnis? Wenn es sich um eine Datei handelt, können Sie den einfachen Befehl touch verwenden. Wenn eine Datei vorhanden ist, wird lediglich die letzte Zugriffszeit geändert. Wenn die Datei nicht vorhanden ist, wird sie erstellt.

Ondra Sniper Flidr
quelle
0

Probier diese. Das lnbietet die Test-and-Set-Funktionalität.

touch lock.$$.tmp
if ln lock.$$.tmp lock.dat 2>/dev/null
then
    echo "File is mine"
else
    echo "Test and set failed"
fi
rm -f lock.$$.tmp
Roaima
quelle
0

Wenn Sie sich nicht für den Dateinamen interessieren, können Sie diese Aufgabe an ein Dienstprogramm delegieren, z. B. mktemp

Create a temporary file or directory, safely, and print its name.
TEMPLATE must contain at least 3 consecutive `X's in last component.
If TEMPLATE is not spec‐ified, use tmp.XXXXXXXXXX, and --tmpdir is 
implied.  Files are created u+rw, and directories u+rwx, minus umask
restrictions.

Aufruf:

filename=$(mktemp)
asdmin
quelle