Preservar carimbo de data / hora modificado após a edição

20

Para arquivos em uma pasta específica, eu gostaria que o vim nunca tocasse no carimbo de data / hora "modificado".

O pano de fundo é que eu uso o Bloxsom para blogs, que usa arquivos de texto sem formatação ~/bloxsomcomo fonte de todos os artigos. A data do artigo (e, portanto, a ordem de exibição) é baseada na data de modificação do arquivo de texto. Não quero que o artigo apareça como se fosse novo sempre que eu corrigir um erro de digitação. (Eu faço muitos deles ...: D)

Até agora, o vim altera o carimbo de data e hora e o carimbo original é perdido para sempre. Tudo bem e quero mantê-lo assim para a maioria dos arquivos no sistema. Mas não quero isso para os arquivos do blog - posso sempre toucho arquivo, se precisar.

Alguma idéia de como ajustar o vim nesse comportamento?

Alois Mahdal
fonte
2
vim.wikia.com/wiki/… - é claro que você pode usar ligações perl em vez disso
Ulrich Dangel

Respostas:

22

Eu não acho que o vim tenha esse recurso. Uma alternativa é modificar uma cópia e definir o carimbo de data / hora adequadamente, por exemplo:

cp -p post temp
vim temp
touch -r post temp
cp -p temp post

Ou melhor ainda:

touch -r post timestamp
vim post
touch -r timestamp post
Thor
fonte
7

Se você precisa se divertir:

file=path; mtime=$(stat -c %y "$file"); vi "$file"; touch -d "$mtime" "$file"

Substitua caminho pelo caminho real do arquivo

Shâu Shắc
fonte
5

Eu escrevi um script Perl para isso.

É um invólucro em torno do vim, salvo ~/bin/vim-nomtime.ple usado alias vim='~/bin/vim-nomtime.pl'em meu .bashrc.

#!/usr/bin/perl
use strict;
use warnings;
use Cwd qw/ abs_path /;

my @dirs = qw( ~/blosxom /srv/relief/blosxom );

s/^~/$ENV{HOME}/ foreach @dirs;

# do we want to preserve stamp on this file?
sub fits {
    my $dir = abs_path($_[0]);
    my $fits = 0;
    foreach (@dirs) {
        my $preserved_dir = abs_path($_);
        $fits++ if $dir =~ m|^$preserved_dir|;
    }
    return $fits != 0;
}

# store original stamps
my $original_stamp;
foreach (@ARGV) {
    if ( -f $_ and fits($_) ) {
        $original_stamp->{$_} = (stat($_))[9];
    }
}

# run vim as you would
my $cmd = join ' ', 'vim', @ARGV;  
system($cmd) == 0
    or die "vim failed: $!";

# restore stamps if they have changed
foreach (keys %$original_stamp) {
    next unless -f $_;
    my $current_stamp = (stat($_))[9];
    unless ($current_stamp == $original_stamp->{$_}) {
        utime $original_stamp->{$_}, $original_stamp->{$_}, $_;
    }
}

Algumas boas características:

  • suporta vários nomes de arquivos

  • suporta múltiplos dirs "assistidos"

  • suporta dir link simbólico

  • pode ser aprimorado com outros critérios

a maioria dos quais provavelmente também poderia ser alcançada com a versão pura do vim. As desvantagens desta solução em comparação à minha solução de vim puro desejada são:

  • restaura o carimbo somente depois que o vim é encerrado; portanto, se eu fizer uma edição longa e salvar regularmente, o arquivo será exibido como novo até que eu saia do vim

  • ele suporta vários arquivos na linha de comando, mas de uma maneira bastante ingênua - apenas verifica se o item @ARGVestá em um arquivo. Provavelmente isso não funcionaria com caracteres curinga (por exemplo vim note-*.txt) ou outras coisas engraçadas

  • não é à prova de falhas, provavelmente nem mesmo à prova de HUP (isso pode ser feito)

  • ... bem, é um invólucro. (Quero dizer, se resolvermos tudo por meio do invólucro, quantos invólucros teríamos antes que algo ruim acontecesse?)

Alois Mahdal
fonte
Em 3 de maio de 2019, e eu apenas modifiquei um arquivo a partir de 11 de novembro de 2017 e ele possui minha modificação e preserva o carimbo de data / hora original. :)
jmort253
1

Este script curto preservará o horário modificado se qualquer diretório pai do arquivo contiver um .nomtimearquivo:

#!/bin/bash

dir="${1%/*}"
[ "$dir" = "$1" ] && dir=.
dir=$( readlink -f "$dir" )

nomtime=
while [ -n "$dir" ]; do
    if [ -f "$dir/.nomtime" ]; then
        nomtime=1
        break
    fi
    dir="${dir%/*}"
done

if [ "$nomtime" = 1 ]; then
    T=`tempfile`
    touch -r "$1" $T
fi

vi "$1"

if [ "$nomtime" = 1 ]; then
    touch -r $T "$1"
    rm $T
fi
Xiè Jìléi
fonte
1

Tente esta bashfunção (com base na resposta de Shâu Shắc )

vi-preserve-time () {
    for file in "$@"; do
        local mtime=$(stat -c %y "$file")
        vi "$file"
        touch -d "$mtime" "$file"
    done
}

Agora podemos editar o arquivo e preservar o tempo modificado usando este

vi-preserve-time file1.txt file2.txt
Asa de aço
fonte
(1) Isso é quase idêntico à resposta de Shâu Shắc de cinco anos atrás. (2) Isso pressupõe que o usuário chama viapenas um único arquivo por vez; não vai funcionar vi file1 file2. (3) Escusado será dizer que, se o usuário mudar para um arquivo diferente :e, ele não será tratado.
G-Man diz 'Reinstate Monica'
Desculpe por esquecer de fazer referência, agora eu adicionei um link de referência à resposta de Shâu Shắc.
Steely Wing
Sobre a sua pergunta nº 3, acho que se você abrir outro arquivo não estiver na linha de comando, é problema seu.
Steely Wing
11
O que quero dizer é que, se a pergunta for "Como posso fazer com que o vim se comporte da maneira que eu quero?", E você fornecer uma função que pareça estar fazendo com que o vim se comporte da maneira que o usuário deseja, é sua responsabilidade documentar quaisquer limitações do seu responda. OK, talvez meu comentário seja um pouco injusto, já que todas as outras respostas parecem ter a mesma limitação, e nenhuma delas menciona isso, até onde eu sei. Eu estava apenas revisando sua resposta porque era nova; Não gastei muito tempo olhando as outras respostas.
G-Man diz 'Reinstate Monica'
1

Há uma opção para copiar um registro de data e hora de outro arquivo.

touch -m -r file_source file_target

Exemplo:

[oracle@es abc]$ ls -tlr
total 4
-rw-r--r--. 1 oracle oinstall 102 May  8 20:35 aa.txt
[oracle@es abc]$ echo "hi hi" > b
[oracle@es abc]$ ls -ltr
total 4
-rw-r--r--. 1 oracle oinstall 102 May  8 20:35 aa.txt
-rw-r--r--. 1 oracle oinstall   6 May 13 18:58 b
[oracle@es abc]$ touch -m -r aa.txt b
[oracle@es abc]$ ls -tlr
total 8
-rw-r--r--. 1 oracle oinstall   6 May  8 20:35 b
-rw-r--r--. 1 oracle oinstall 102 May  8 20:35 aa.txt
[oracle@es abc]$ cat b
hi hi
user352752
fonte
1

Encontrei uma ótima solução nesta página da web , que cria uma função vim para salvar o arquivo atual, preservando o tempo de modificação existente, e vincula essa função à F4tecla de função:

No entanto, descobri que a função original contém um bug menor, acionando o seguinte aviso se F4for usado duas vezes no mesmo arquivo, porque o vim fica confuso quando o tempo de modificação é alterado:

WARNING: The file has been changed since reading it!!!
Do you really want to write to it (y/n)?

Felizmente, isso é fácil de corrigir: adicionei um comando "edit" à função original para recarregar o arquivo depois de restaurar o carimbo de data / hora, para que o vim saiba que hora de modificação você espera que o arquivo tenha.

Aqui está a função vim modificada com esta correção de bug, que pode ser adicionada a ~/.vimrc:

function! WriteSmall()
    let mtime = system("date -d @`stat -c %Y ".shellescape(expand('%:p')) . "`")
    write
    call system("touch --date='".mtime."' ".shellescape(expand('%:p')))
    edit
endfunction
map <F4> :call WriteSmall()<CR>

Nota: Esta função depende das versões GNU de date, state touch.

Deven T. Corzine
fonte
0

Usando alguns dos conceitos descritos acima, aqui está um alias de uma linha muito rápido e sujo para CSH, que disponibiliza um comando "edit" para este fim:

alias edit 'touch -r \!:1 /tmp/~mtime ; vim \!:1 ; touch -r /tmp/~mtime \!:1 ; rm /tmp/~mtime'

Você pode facilmente usar a variável de ambiente $ VISUAL ou $ EDITOR no lugar de "vim". Dessa forma, você pode emitir o seguinte comando para alterar os editores padrão

setenv VISUAL nano

Agora, o próprio alias não precisa ser redefinido para acomodar diferentes editores, tornando-o um pouco mais portátil. Se você usar um shell que não seja CSH ou TCSH, é claro, os exemplos acima podem ser adaptados de acordo.

Leslie Krause
fonte