Eine feste Verbindung herstellen?

13

Ich halte meine Punktedateien unter Versionskontrolle und das Skript, das sie bereitstellt, erstellt feste Links. Ich benutze auch etckeeper, um meine /etcunter Versionskontrolle zu setzen . Vor kurzem habe ich Warnungen wie diese erhalten:

warning: hard-linked files could cause problems with bzr

Eine einfache Kopie ( cp filename.ext filename.ext) funktioniert nicht:

cp: `filename.ext' and `filename.ext' are the same file

Das Umbenennen / Verschieben einer Datei - außer über mehrere Volumes hinweg - unterbricht auch nicht die feste Verbindung.

Meine Frage lautet also: Gibt es eine Möglichkeit, einen Hardlink zu einer Datei zu unterbrechen, ohne tatsächlich wissen zu müssen, wo sich die anderen Hardlinks zu dieser Datei befinden?

0xC0000022L
quelle
2
Der Befehl "rm" unterbricht harte Verbindungen.
Johan

Antworten:

14
cp -p filename filename.tmp
mv -f filename.tmp filename

Skriptfähig machen:

dir=$(dirname -- "$filename")
tmp=$(TMPDIR=$dir mktemp)
cp -p -- "$filename" "$tmp"
mv -f -- "$tmp" "$filename"

Wenn Sie die Kopie zuerst erstellen und dann an ihren Platz verschieben, hat dies den Vorteil, dass sich die Datei atomar von einer festen Verknüpfung zu einer separaten Kopie ändert (es gibt keinen Zeitpunkt, an dem sie filenameteilweise vorhanden ist oder fehlt).

Gilles 'SO - hör auf böse zu sein'
quelle
7

Sie meinen wahrscheinlich, dass Sie den Hardlink in eine separate, unabhängige Datei aufteilen möchten.

mv hardlink tempname && cp tempname hardlink && rm tempname

Ein Hardlink ist die Verbindung zwischen einem Eintrag im Verzeichnis und dem Inode-Block auf der Festplatte.

Inodes speichern Datei-Metadaten, und für kleine Dateien speichern einige Dateisysteme Daten im Inode, andernfalls Zeiger auf die Datenblöcke und für sehr große Dateien indirekte und doppelt indirekte Listen von Zeigern auf Plattenzuordnungseinheiten.

Unabhängig davon wird die Verbindung zwischen dem Dateinamen (den der Befehl ls erzeugt) und dem Inode-Block, in dem diese Metadaten gespeichert sind, als fester Link bezeichnet.

Mehrere feste Links zu einer einzelnen Datei bedeuten, dass derselbe Inode von mehr als einem Verzeichniseintrag referenziert wird, möglicherweise in verschiedenen Verzeichnissen (in einem einzelnen Dateisystem).

rm löscht den Dateinameneintrag aus dem Verzeichnis. Sobald ein Inode nicht mehr von Dateien referenziert wird, wird sein Speicherplatz für die Verwendung durch andere Dateien freigegeben.

Johan
quelle
Tatsächlich. Dies ist, was die cpund mvBeispiele implizierten. Ich verstehe also, dass es keinen Weg gibt, eine temporäre Datei zu verwenden.
0xC0000022L
@ 0xC0000022L, Nein, Inodes enthalten keine Zeiger auf andere Inodes. Nur für Datenblöcke (oder sie können als Datenraum dienen, wenn das Objekt klein ist).
vonbrand
4
Stellen Sie sicher, dass die Berechtigungen und andere Daten beim Kopieren erhalten bleiben, d. H. verwenden cp -a(mindestens GNU Coreutils).
vonbrand
@ 0xC0000022L, wenn Sie genau hinschauen, gibt es nur einen temporären Namen für die Originaldatei, eine neue Datei wird erst im letzten Schritt erstellt.
vonbrand
@vonbrand Sie können in der Tat, je nachdem, welches Dateisystem verwendet wird.
Johan
3

Fügen Sie dies am Ende Ihrer ~ / .bashrc-Datei ein.

delink () { tmpfile="$1$(date)"; cp -a "$1" "$tmpfile"; mv "$tmpfile" "$1"; }

Führen Sie es so aus

delink filename
Rucent88
quelle
3

Der beste Weg, dies mit einem Bash-Skript zu tun, wäre ungefähr so:

if [ -f "$1" ] ; then
dir="$(dirname -- "$1")"
tmpfile="$(mktemp --tmpdir="$dir")"
cp --preserve=all -f -- "$1" "$tmpfile"
mv -f -- "$tmpfile" "$1"
fi

Punkte zu beachten:

  • Überprüfen Sie, ob es sich bei der Datei um eine reguläre Datei handelt, bevor Sie versuchen, sie zu kopieren
  • Behalten Sie die alte Datei bei, bis die Kopie fertig ist
  • Verwenden Sie mktempdiese Option, um eine Datei zu generieren, die garantiert nicht vorhanden ist
  • Verwenden Sie -fdiese Option --preserve=all, um das Überschreiben zu erzwingen und die Metadaten der Originaldatei so ähnlich wie möglich zu halten
  • Verwenden Sie --und ", um Pfade zu zitieren, die Leerzeichen enthalten und / oder mit beginnen-

Das Ersetzen ohne Erstellen einer temporären Datei ist mit aktuellen (3.16) Linux-Systemaufrufen nicht möglich: Während es möglich ist, eine Datei atomar zu überschreiben (dh die alte Datei zu entfernen und als einzelne Operation durch eine neue zu ersetzen), ist dies möglich ist nicht möglich , dies mit einer Datei zu tun , die auf dem Dateisystem keinen Namen (dh eine temporäre Datei erstellt unter Verwendung der hat O_TMPFILEFlagge openFunktion) , da die renameFunktion einen Dateinamen als Eingang (es erforderlich ist keine Version von renamedem als Eingabe - Descriptor eine Datei nimmt - siehe hier für Details)

pqnet
quelle
1
Beachten Sie, dass Sie den Namen in Ihrem dirnameund mktempAnrufen nicht angegeben haben.
Behoben,
@derobert oh danke, aber das wird nicht funktionieren, da es verschachtelte doppelte Anführungszeichen gibt ... brauche einen anderen Fix! Ein
bisschen
3
Es funktioniert aufgrund der $( ... )Ersetzung des Befehls -style. Ein Grund, warum es schöner ist als ` ... `Stil.
Derobert
@derobert nett, wusste das nicht. Wie können Sie auch Inside-Inline-Code-Tags verwenden?
pqnet
Sie können ihnen mit Backslashes entkommen. Um `Sie dazu zu bringen: `\``(Natürlich bin ich dem doppelt entkommen, damit es Ihnen zeigt, was Sie eingeben).
Derobert
-1

Der Befehl, den Sie suchen, ist unlink

Jenny D.
quelle
Vielleicht war meine Frage nicht klar, aber durch "an Ort und Stelle" und die Beispiele mit cpund mvich wollte klarstellen, dass ich möchte, dass die Datei danach existiert.
0xC0000022L
Ah, das fand ich nicht klar, nein. Dann sollten Sie Johans Antwort folgen.
Jenny D
1
Der Befehl "Verknüpfung aufheben" entfernt einfach die Datei (was der Systemaufruf "unlink ()" bewirkt).
Raúl Salinas-Monteagudo
-1

Wenn Sie nach allen Dateinamen suchen, die mit dieser Datei verknüpft sind, können Sie Folgendes verwenden:

find -samefile myknowhardlinkfile

Außerdem ls -il myknowhardlinkfilewird die Anzahl der Dateinamen angezeigt, die mit demselben Inode verknüpft sind (drittes Feld).

101612442 -rw-rw-r--. 2 me me 0 Aug  5 07:07 myknowhardlinkfile
Jean-Pierre Laurin
quelle
Dies beantwortet die Frage nicht wirklich, obwohl es nützlich sein könnte.
Flimm