Come mv una cartella in Linux mantenendo il suo mtime?


12

Sto usando CentOS 5.5 e vorrei spostare una grande quantità di cartelle all'interno di un volume , mantenendo il loro mtime.

La migliore soluzione che ho potuto trovare è questa:

cp -p -r source/data target/
rm -rf source/data

Con oltre 1 TB di dati su una condivisione NFS, la copia richiede un'eternità. Non voglio copiare. Voglio una mossa istantanea.

Quando sposto una cartella usando mv source/data target/, la mtimecartella (non i file) viene impostata sull'ora corrente. Questo perché il contenuto della cartella che sto spostando viene modificato da questa operazione (la ..voce punta a un altro inode).

Mi è venuta in mente una seguente shell script che ho chiamato mv_preserve_mtime.sh:

#!/bin/bash
# Moves source folder to target folder. 
# You are responsible for making sure the target does not exist, otherwise this blows up
export timestamp=`stat -c %y $1`
mv "$1" "$2"
touch --date="${timestamp}" $2

Bene, neanche quello ha funzionato. La cartella mtimeviene ripristinata, ma tutte le cartelle all'interno della cartella che sposto (solo quelle a 1 livello di profondità) ottengono il loro mtimeripristino per motivi che non capisco.

Qualcuno ha una soluzione adeguata, efficiente e corretta?


Mi chiedo perché il tuo tentativo con touchnon ha funzionato. È il mvpassaggio o il touchpassaggio che modifica il mtime delle sottodirectory? Quale sistema operativo si trova sul server NFS e (se si conosce) quale tipo di file system?
Gilles 'SO- smetti di essere malvagio' il

@Gilles: non so perché stia succedendo. È il mvpassaggio che causa problemi. Il server NFS è in realtà un archivio NetApp, non so praticamente nulla dei suoi interni.
Roman Zenka,

1
Grazie. Sospetto che sia una stranezza di NetApp. Altrimenti touchavrebbe dovuto funzionare. A proposito sarebbe un modo più portatile touch -r "$1" reference.tmp; mv -- "$1" "$2"; touch -r reference.tmp -- "$2"; rm reference.tmp.
Gilles 'SO- smetti di essere malvagio' il

@Gilles: Molto interessante, non mi rendevo conto che statnon era portatile.
Roman Zenka,

Risposte:


15

POSIX mvnon fornisce alcuna opzione per richiedere la conservazione atime / mtime, ma poiché l'operazione è locale su uno stesso volume, è possibile chiedere cpdi utilizzare i collegamenti reali invece di copiare i dati dei file normali utilizzando l' -lopzione:

cp -p -r -l source/date target/
rm -rf source/data

Poiché solo le directory e i riferimenti ai file verranno effettivamente copiati, dovrebbe andare molto più veloce:

Per ulteriori informazioni sugli hard link, è possibile consultare la pagina Wikipedia corrispondente

Per quanto riguarda il motivo per cui le sottodirectory mtime vengono ripristinate con la soluzione corrente, è perché si ottiene e ripristina solo la directory principale mtime: touch non è un comando ricorsivo.


Il mtime è più complicato di così. Solo la directory padre e le directory direttamente sotto di essa sono state modificate. Tutte le altre directory rimangono le stesse. Ci si aspetterebbe di modificare ogni singola directory o solo il genitore.
Roman Zenka,

1
In realtà, ha senso: 1) La directory padre ha il mtime buono perché è stata impostata esplicitamente al tocco, 2) Le voci della directory sono state ricreate con la directory padre, ma il loro mtime non è stato ripristinato manualmente (struttura della directory Unix e formato inode) 3) Il resto della struttura ad albero non è stato effettivamente modificato, poiché siamo rimasti sullo stesso volume: ecco perché mvnon esiste un'opzione "ricorsiva", la discesa in sottodirectory viene eseguita solo se è necessaria una copia effettiva (volumi diversi, ad esempio).
Eureka,

@Eureka: buona spiegazione, ma perché è fatto in questo modo? Se fossi di implementare mvsu una directory data, vorrei semplicemente cambiare l' ..nel datacontenuto 's e modificare le sourcee targetdirectory per elencare l'oggetto spostato correttamente. Nessun'altra directory dovrebbe essere toccata.
Roman Zenka,

1
@Roman Zenka Dopo alcune ricerche, questo comportamento sembra essere piuttosto vagamente specificato tra Unices e filesystem e dipende molto renamedall'implementazione di syscall sottostante da parte del kernel e del / i filesystem / i usato / i, NFS aggiungendo la sua condivisione al problema. Ci sono alcuni puntatori che fanno riferimento a questo tipo di incoerenze: patchwork.ozlabs.org/patch/25833 bugs.opensolaris.org/bugdatabase/…
Eureka,

@Eureka: trovo estremamente difficile credere che qualcosa che considererei così semplice possa essere un tale casino. È quasi il 2011. Grazie per quelle risorse!
Roman Zenka,

4

Un'altra soluzione potrebbe essere:

rsync -a --remove-source-files source / data target /


Questo non sembra funzionare su macOS.
Lenar Hoyt,
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.