Configura os registros de data e hora do diretório para o arquivo modificado mais recentemente (recursivamente)

4

Como altero o registro de data e hora de um diretório e de todas as subpastas dentro desse diretório para refletir os horários de modificação dos arquivos contidos?

Por exemplo, com esta estrutura de diretórios:

[Jan 9]  root
├── [Jan 3]  file1
├── [Jan 7]  file2
├── [Jan 6]  sub1
│   ├── [Jan 2]  file3
│   └── [Jan 1]  file4
└── [Jan  4] sub2
    └── [Jan 8]  file5

Aqui está um folheto para gerar isso:

mkdir -p root/sub1 root/sub2 && touch -d '2018-01-08' root/sub2/file5 && touch -d '2018-01-04' root/sub2/ && touch -d '2018-01-01' root/sub1/file4 && touch -d '2018-01-02' root/sub1/file3 && touch -d '2018-01-06' root/sub1/ && touch -d '2018-01-07' root/file2 && touch -d '2018-01-03' root/file1 && touch -d '2018-01-09' root/

Pode ser listado com tree -D

Gostaria de alterar os timestamps nos três diretórios a serem:

[Jan 8]  root
├── [Jan 3]  file1
├── [Jan 7]  file2
├── [Jan 2]  sub1
│   ├── [Jan 2]  file3
│   └── [Jan 1]  file4
└── [Jan 8]  sub2
    └── [Jan 8]  file5

Nota:

  • Os registros de data e hora atuais nos diretórios são completamente ignorados e os novos registros de data e hora são definidos somente com base no conteúdo.
  • Os carimbos de data / hora borbulham para vários níveis de diretórios pai.

O motivo que estou fazendo isso é para um diretório que é copiado com o rsync. O diretório é verificado no git e pode receber o rsynced de qualquer lugar que tenha o repositório com check-out. Para garantir que o rsync seja consistente e idempotente dos vários locais, preciso garantir que os registros de data e hora e as permissões de tudo estejam em um estado conhecido. Eu já tenho um script que define os registros de data e hora dos arquivos com base em quando eles foram confirmados para o git. Eu também tenho um script que define as permissões em todos os arquivos e diretórios para um estado conhecido. A única parte com a qual eu estou me esforçando é borbulhando registros de horário dos arquivos até os diretórios pai.

Gostaria que uma linha ou script curto pudesse ser executado a partir da linha de comando para definir registros de data e hora do diretório com base nos registros de data e hora de seu conteúdo.

    
por Stephen Ostermiller 10.01.2018 / 12:45

2 respostas

2

Se você pode usar o Zsh, isso parece fazer o que você deseja:

$ mkdir -p x/y; touch x/y/a x/b; sleep .1; touch x/y/a; sleep .1; touch x/b
$ find -depth -type d -execdir zsh -c 'touch "$1" -r "$1"/*(om[1])' zsh {} \;

Teste a saída com o GNU find, ./x/b foi o mais novo, seu timestamp é copiado para ./x e . .

$ find -printf "%TT %p\n"  | sort -n
15:16:24.0182222830 ./x/y
15:16:24.0182222830 ./x/y/a
15:16:24.1222150510 .
15:16:24.1222150510 ./x
15:16:24.1222150510 ./x/b

Encontrar o arquivo mais novo por timestamp é um pouco complicado em geral, se houver nomes de arquivos com espaço em branco / novas linhas ou algo parecido. (Veja BashFAQ 099 .) Zsh facilita bastante, no entanto, o truque acima é de É possível referenciar o arquivo modificado mais recentemente em um argumento de linha de comando?

-depth informa find para manipular subdiretórios antes de seus pais, para que o borbulhamento realmente funcione.

Isso não ignora totalmente os registros de data e hora dos diretórios, pois eles devem ser contados quando os registros de data e hora se elevarem. Um diretório contendo arquivos receberá seu registro de data e hora dos arquivos, mas um diretório vazio manterá seu registro de data e hora original, e esse registro de tempo será borbulhado. Não tenho certeza se vale a pena trabalhar com isso.

    
por 10.01.2018 / 14:29
1

A menos que eu esteja ignorando algo (não testei isso extensivamente):

find . -depth -type d -execdir \
    sh -c 'touch "$PWD/$0" -r "$PWD/$0/$( ls -t "$PWD/$0" | head -n 1 )"' \
    {} \;

O que faz:

  • localiza todos os subdiretórios de.
  • busca seus nomes completos
  • com ls -t , lista seu conteúdo em ordem de data reversa e obtém o primeiro
  • usa touch para tocar no diretório usando seu mais novo objeto como timestamp

Para datetime "bubbling" correto, a opção -depth garante que os subdiretórios sejam processados antes do subdiretório atual ("profundidade primeiro"). Depois que os subdiretórios forem processados e seus dados atualizados, o diretório atual será processado (e possivelmente herdará um dos registros de data e hora dos subdiretórios filhas).

    
por 10.01.2018 / 13:07