Rompere tutti gli hardlink all'interno di una cartella


10

Ho una cartella che contiene un certo numero di file che hanno collegamenti fissi (nella stessa cartella o altrove) e desidero scollegare questi file in modo che diventino indipendenti e le modifiche al loro contenuto non influiranno su altro file (il loro conteggio dei collegamenti diventa 1).

Di seguito, fornisco una soluzione che sostanzialmente copia ogni collegamento reale in un'altra posizione, quindi lo sposta di nuovo in posizione.

Tuttavia, questo metodo sembra piuttosto rozzo e soggetto a errori, quindi mi piacerebbe sapere se esiste un comando che scollegherà un file per me.

Risposta grezza:

Trova file con collegamenti fissi ( Modifica : per trovare anche socket ecc. Con collegamenti fissi, utilizzare find -not -type d -links +1):

find      -type f -links +1 # files only
find -not -type d -links +1 # files, sockets etc.

Un metodo grezzo per de-hardlink di un file (copiarlo in un'altra posizione e spostarlo indietro): Modifica: Come ha detto Celada, è meglio fare un cp -p di seguito, per evitare di perdere timestamp e autorizzazioni. Modifica: crea una directory temporanea e copia in un file al suo interno, invece di sovrascrivere un file temporaneo, riduce al minimo il rischio di sovrascrivere alcuni dati, sebbene il mvcomando sia ancora rischioso (grazie a @Tobu). Modifica: prova a creare la directory temporanea nello stesso filesystem (@MikkoRantalainen).

# This is unhardlink.sh
set -e
for i in "$@"; do
  temp="$(mktemp -d -- "${i%/*}/hardlnk-XXXXXXXX")"
  [ -e "$temp" ] && cp -ip "$i" "$temp/tempcopy" && mv "$temp/tempcopy" "$i" && rmdir "$temp"
done

Quindi, per annullare il collegamento di tutti gli hard link ( Modifica : modificato -type fin -not -type d, vedi sopra):

find -not -type d -links +1 -print0 | xargs -0 unhardlink.sh

Non lo considero "rozzo". L'unico modo per farlo più velocemente è probabilmente fare qualche trucco con la chiamata di sistema sendfile () e scollegare il file open source e riscrivere la destinazione sul posto. Francamente non ne vale la pena però.
Matthew Ife,

Con 'grezzo', voglio dire che, ad esempio, quando mi sono imbattuto questo comando utilizzando l' cp -iinterruttore, sputato verso di me un paio di messaggi chiedendo se deve ignorare ./fileXXXXXX(il $tempfile), anche se tmpfile dovrebbe dare nomi di file univoci, quindi non deve essere una sorta di condizione di gara o altro, e con essa il rischio di perdere alcuni dati.
Suzanne Dupéron,

1
È normale che il file esista, lo hai appena creato con tempfile (nb: deprecato a favore di mktemp, ma non è questo che ha causato il tuo problema).
Tobu,

1
Il tuo unhardlink.shdovrebbe creare la directory temporanea all'interno della stessa directory che contiene il file che deve essere unhardlinked. Altrimenti la tua chiamata ricorsiva potrebbe ricorrere all'interno di un altro filesystem e finirai per spostare roba oltre i confini del filesystem perché la tua directory temporanea è nella directory di lavoro corrente. Immagino che potresti passare "$(dirname "$i")/hardlink-XXXXXX"come argomento a mktemp invece.
Mikko Rantalainen,

1
@MikkoRantalainen Grazie mille, aggiornato! Nota che se il filesystem è una sorta di unionfs o un fusefilesystem, potrebbe effettivamente essere inviato path/to/hardlink-XXXa un supporto di archiviazione fisico diverso da quello path/to/original-file, ma non c'è molto che si possa fare al riguardo.
Suzanne Dupéron,

Risposte:


9

Vi sono margini di miglioramento nello script, ad esempio l'aggiunta di -pun'opzione al cpcomando in modo che le autorizzazioni e i timestamp vengano conservati attraverso l'operazione di non collegamento e si potrebbe aggiungere un po 'di gestione degli errori in modo che il file temporaneo venga eliminato in caso di errore, ma l'idea di base della tua soluzione è l'unica che funzionerà. Per annullare il collegamento di un file, è necessario copiarlo, quindi spostare nuovamente la copia sul nome originale. Non esiste una soluzione "meno grezza" e questa soluzione presenta condizioni di competizione nel caso in cui un altro processo acceda contemporaneamente al file.


In effetti, uso sempre cp -a quando copio roba, per preservare tutto, ricorrere e copiare link simbolici come link simbolici. Non so perché questa volta l'ho dimenticato, ma dopo aver visto la tua risposta, ho capito che avevo rovinato tutti i miei timestamp e che dovevo (piuttosto dolorosamente) recuperarli da un backup.
Suzanne Dupéron,

5

Se vuoi bruciare spazio su disco e hai una versione relativamente moderna di tar(ad esempio, cosa c'è su Ubuntu 10.04 e CentOS 6), puoi giocare con l' --hard-dereferenceopzione.

Qualcosa di simile a:

$ cd /path/to/directory
$ ls -l *
bar:
total 12
-rw-rw-r-- 2 cjc cjc 2 May  6 19:07 1
-rw-rw-r-- 2 cjc cjc 2 May  6 19:07 2
-rw-rw-r-- 1 cjc cjc 2 May  6 19:07 3

foo:
total 12
-rw-rw-r-- 2 cjc cjc 3 May  6 19:07 1
-rw-rw-r-- 2 cjc cjc 2 May  6 19:07 2
-rw-rw-r-- 1 cjc cjc 2 May  6 19:07 4

(dove avevo corso ln foo/[12] bar)

$ tar cvf /tmp/dereferencing.tar --hard-dereference .
$ tar xvf /tmp/dereferencing.tar
$ ls -l *
bar:
total 12
-rw-rw-r-- 1 cjc cjc 2 May  6 19:07 1
-rw-rw-r-- 1 cjc cjc 2 May  6 19:07 2
-rw-rw-r-- 1 cjc cjc 2 May  6 19:07 3

foo:
total 12
-rw-rw-r-- 1 cjc cjc 3 May  6 19:07 1
-rw-rw-r-- 1 cjc cjc 2 May  6 19:07 2
-rw-rw-r-- 1 cjc cjc 2 May  6 19:07 4

Dalla pagina man:

   --hard-dereference
          follow hard links; archive and dump the files they refer to

Sospetto che non ci sia poco da fare. Bella soluzione.
Joseph Kern,

Ho dimenticato di dire che non avevo abbastanza spazio su disco per copiare tutto. Fondamentalmente, il tuo metodo è lo stesso di cp -a --no-preserve=links /path/to/folder /path/to/copy && rm -rf /path/to/folder && mv /path/to/copy /path/to/folder, se non sbaglio. Immagino che il tuo metodo sarebbe più efficiente, però, perché tar comporterebbe meno ricerche del disco, quindi meno thrashing. Si potrebbe ottenere lo stesso con rsync, con prestazioni persino inferiori rispetto al metodo cp :).
Suzanne Dupéron,

1
Per evitare di usare molto altro disco, potrebbe essere possibile eseguire qualcosa del genere tar cvf - --hard-dereference . | tar xf -ma potrebbe esserci una condizione di competizione che farà esplodere le cose. Non l'ho provato e al momento non sono propenso a farlo.
cjc
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.