Como mv uma pasta no Linux mantendo seu mtime?

12

Estou usando o CentOS 5.5 e gostaria de mover uma grande quantidade de pastas em um volume , mantendo-as mtime.

A melhor solução que eu poderia encontrar é assim:

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

Com mais de 1 TB de dados em um compartilhamento NFS, a cópia leva uma eternidade. Eu não quero copiar Eu quero movimento instantâneo.

Quando movo uma pasta usando mv source/data target/, a mtimepasta (e não os arquivos) é definida para a hora atual. Isso ocorre porque o conteúdo da pasta que estou movendo é modificado por esta operação (a ..entrada está apontando para um inode diferente).

Eu vim com um seguinte script de shell que chamei 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

Bem, isso também não funcionou. A pasta mtimeé restaurada, mas todas as pastas dentro da pasta que eu movo (apenas as que têm 1 nível de profundidade) são mtimerestauradas por motivos que não compreendo.

Alguém tem uma solução adequada, eficiente e correta?

Roman Zenka
fonte
Eu me pergunto por que sua tentativa com touchnão funcionou. É a mvetapa ou a touchetapa que altera o mtime dos subdiretórios? Qual sistema operacional está no servidor NFS e (se você souber) que tipo de sistema de arquivos?
Gilles 'SO- stop be evil'
@ Gilles: Eu não sei por que isso está acontecendo. É o mvpasso que causa problemas. O servidor NFS é na verdade um armazenamento da NetApp, não sei praticamente nada sobre seus componentes internos.
Roman Zenka
1
Obrigado. Suspeito que seja uma esquisitice da NetApp. Caso contrário, touchdeveria ter funcionado. A propósito, uma maneira mais portátil seria touch -r "$1" reference.tmp; mv -- "$1" "$2"; touch -r reference.tmp -- "$2"; rm reference.tmp.
Gilles 'SO- stop be evil'
@ Gilles: Muito interessante, não sabia que não statera portátil.
Roman Zenka

Respostas:

15

O POSIX mvnão fornece nenhuma opção para solicitar preservação atime / mtime, mas como a operação é local em um mesmo volume, você pode solicitar o cpuso de links físicos em vez de copiar dados dos arquivos regulares usando a -lopção:

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

Como apenas diretórios e referências de arquivo serão realmente copiados, deve ser muito mais rápido:

Para mais informações sobre links físicos, você pode consultar a página correspondente da Wikipedia

Por que os subdiretórios mtime estão sendo redefinidos com a solução atual, é porque você apenas obtém e restaura o diretório pai mtime: touch não é um comando recursivo.

Eureka
fonte
O tempo é mais complicado que isso. Somente o diretório pai e os diretórios diretamente sob ele foram alterados no mtime. Todos os outros diretórios permanecem os mesmos. Seria de esperar que cada diretório único fosse alterado ou apenas o pai.
Roman Zenka
1
Na verdade, faz sentido: 1) O diretório pai possui o mtime bom porque foi explicitamente definido por toque, 2) As entradas do diretório foram recriadas com o diretório pai, mas o mtime não foi restaurado manualmente (estrutura de diretório Unix e formato de inode) 3) O restante da estrutura da árvore não foi realmente alterado, pois permanecemos no mesmo volume: é por isso mvque não há opção "recursiva", a descida em subdiretórios é feita apenas se a cópia real (volumes diferentes, por exemplo) for necessária.
Eureka
@Eureka: Boa explicação, mas por que isso é feito dessa maneira? Se eu fosse para implementar mvem um diretório data, eu simplesmente mudar o ..no dataconteúdo 's e modificar as sourcee targetdiretórios para listar o item movido corretamente. Nenhum outro diretório precisaria ser tocado.
Roman Zenka
1
@ Zenoman Romano Após algumas pesquisas, esse comportamento parece ser vagamente especificado entre os Unices e os sistemas de arquivos e depende muito da renameimplementação subjacente do syscall pelo kernel e pelo (s) sistema (s) de arquivos usado (s), o NFS adicionando seu compartilhamento ao problema. Há algum ponteiro referenciando esse tipo de inconsistências: patchwork.ozlabs.org/patch/25833 bugs.opensolaris.org/bugdatabase/…
Eureka
@Eureka: Acho extremamente difícil acreditar que algo que eu consideraria tão básico possa ser uma bagunça. Estamos quase em 2011. Obrigado por esses recursos!
Roman Zenka
4

Outra solução pode ser:

rsync -a --remove-source-files origem / destino de dados /

Genjo
fonte
Isso parece não funcionar no macOS.
Lenar Hoyt