Conservar la marca de tiempo modificada después de editar

20

Para los archivos dentro de una carpeta específica, me gustaría que vim nunca toque la marca de tiempo "modificada".

El fondo es que uso Bloxsom para bloguear, que usa archivos de texto sin formato ~/bloxsomcomo fuente de todos los artículos. La fecha del artículo (y, por lo tanto, el orden de aparición) se basa en la fecha de modificación del archivo de texto. No quiero que aparezca un artículo emergente como si fuera nuevo cada vez que soluciono un error tipográfico. (Hago muchos de ellos ...: D)

Hasta ahora, vim cambia la marca de tiempo y el sello original se pierde para siempre. Esto está bien y quiero mantenerlo así para la mayoría de los archivos en el sistema. Pero no quiero eso para los archivos del blog; siempre touchpuedo usar el archivo si lo necesito.

¿Alguna idea sobre cómo ajustar vim en este comportamiento?

Alois Mahdal
fuente
2
vim.wikia.com/wiki/… - por supuesto , puedes usar enlaces perl en su lugar
Ulrich Dangel

Respuestas:

22

No creo que vim tenga esta característica. Una alternativa es modificar una copia y establecer la marca de tiempo adecuadamente, por ejemplo:

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

O mejor:

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

Si necesitas divertirte un poco:

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

Reemplace la ruta con su ruta de archivo real

Shâu Shắc
fuente
5

Escribí un script de Perl para eso.

Es un contenedor alrededor de vim, guardado ~/bin/vim-nomtime.ply puesto en uso a través alias vim='~/bin/vim-nomtime.pl'de mi .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->{$_}, $_;
    }
}

Algunas buenas características:

  • admite múltiples nombres de archivo

  • admite múltiples directorios "vistos"

  • soporta dir enlazado

  • se puede mejorar con otros criterios

la mayoría de los cuales probablemente también se podría lograr con la versión vim pura. Las desventajas de esta solución en comparación con mi solución pura de vim deseada son:

  • restaura el sello solo después de que vim ha salido, así que si hago una edición larga y la guardo regularmente, el archivo aparecerá como "emergente" como nuevo hasta que salga de vim

  • admite varios archivos en la línea de comandos, pero de una manera bastante ingenua: solo comprueba si el @ARGVarchivo es un archivo. Esto probablemente no funcionaría con comodines (por ejemplo vim note-*.txt) u otras cosas divertidas

  • no es a prueba de choques, probablemente ni siquiera a prueba de HUP (eso podría hacerse)

  • ... bueno, es una envoltura. (Quiero decir, si resolviéramos todo a través de wrapper, ¿cuántos wrappers tendríamos antes de que algo malo sucediera?)

Alois Mahdal
fuente
3 de mayo de 2019, y acabo de modificar un archivo del 11 de noviembre de 2017 y tiene mi modificación y conserva la marca de tiempo original. :)
jmort253
1

Este breve script conservará el tiempo modificado si algún directorio principal del archivo contiene un .nomtimearchivo:

#!/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
fuente
1

Pruebe esta bashfunción ( basada en la respuesta 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
}

Ahora podemos editar el archivo y preservar el tiempo modificado usando esto

vi-preserve-time file1.txt file2.txt
Ala de acero
fuente
(1) Esto es casi idéntico a la respuesta de Shâu Shắc de hace cinco años. (2) Esto supone que el usuario invoca vien un solo archivo a la vez; no va a funcionar para vi file1 file2. (3) No hace falta decir que, si el usuario cambia a un archivo diferente :e, no se manejará.
G-Man dice 'Restablece a Mónica' el
Lo siento por olvidar hacer referencia, ahora agregué un enlace de referencia a la respuesta de Shâu Shắc
Steely Wing
Sobre su pregunta # 3, creo que si abre otro archivo que no está en la línea de comando, es su problema.
Steely Wing
1
Mi punto es que si la pregunta es "¿Cómo puedo hacer que vim se comporte de la manera que quiero?", Y usted proporciona una función que parece que hace que vim se comporte de la manera que el usuario lo desea, es su responsabilidad documentar cualquier limitación de su responder. OK, tal vez mi comentario es un poco injusto, en la medida en que todas las otras respuestas parecen tener la misma limitación, y ninguna de ellas lo menciona, por lo que puedo decir. Estaba revisando tu respuesta porque era nueva; No pasé mucho tiempo mirando las otras respuestas.
G-Man dice 'Restablece a Mónica' el
1

Hay una opción para copiar una marca de tiempo de otro archivo.

touch -m -r file_source file_target

Ejemplo:

[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
usuario352752
fuente
1

Encontré una gran solución en esta página web , que crea una función vim para guardar el archivo actual al tiempo que conserva el tiempo de modificación existente, y vincula esta función a la F4tecla de función:

Sin embargo, descubrí que la función original contiene un error menor, activando la siguiente advertencia si F4se usa dos veces en el mismo archivo, porque vim se confunde cuando cambia el tiempo de modificación:

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

Afortunadamente, esto es fácil de solucionar: agregué un comando "editar" a la función original para volver a cargar el archivo después de restaurar la marca de tiempo, por lo que vim sabe qué hora de modificación esperará que tenga el archivo.

Aquí está la función vim modificada con esta corrección de errores, que se puede agregar 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 función se basa en las versiones de GNU de date, staty touch.

Deven T. Corzine
fuente
0

Usando algunos de los conceptos descritos anteriormente, aquí hay un alias de una línea muy rápido y sucio para CSH que hace que un comando "editar" esté disponible para este propósito:

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

Puede usar fácilmente la variable de entorno $ VISUAL o $ EDITOR en lugar de "vim". De esta manera, puede emitir el siguiente comando para cambiar los editores predeterminados

setenv VISUAL nano

Ahora el alias en sí no necesita ser redefinido para acomodar a diferentes editores, lo que lo hace algo más portátil. Si utiliza un shell distinto de CSH o TCSH, por supuesto, los ejemplos anteriores se pueden adaptar en consecuencia.

Leslie Krause
fuente