編集後に変更されたタイムスタンプを保持


20

特定のフォルダー内のファイルの場合、vimが「変更された」タイムスタンプにまったく触れないようにします。

背景は、すべての記事のソースとしてプレーンテキストファイルを使用するBlogoxにBloxsomを使用していること~/bloxsomです。記事の日付(したがって、出現順)は、テキストファイルの変更日に基づいています。タイプミスを修正するたびに新しい記事のように記事がポップアップ表示されないようにします。(私は それらの多くをします...:D)

これまでのところ、vimはタイムスタンプを変更し、元のスタンプは永久に失われます。これは問題ありません。システム上のほとんどのファイルについて、そのように保ちたいと思います。しかし、私はブログのファイルにはそれを望んでいません- touch必要であればいつでもファイルを作成できます。

vimをこの動作に微調整する方法に関するアイデアはありますか?


2
vim.wikia.com/wiki/... -することができます代わりに、もちろん利用のperlバインディングの
ウルリッヒ・Dangel

回答:


22

vimにこの機能があるとは思わない。代替方法の1つは、コピーを変更してタイムスタンプを適切に設定することです。例:

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

またはさらに良い:

touch -r post timestamp
vim post
touch -r timestamp post

7

楽しみが必要な場合:

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

パスを実際のファイルパスに置き換えます


5

そのためのPerlスクリプトを書きました。

これはvimのラッパーで~/bin/vim-nomtime.plあり、保存さalias vim='~/bin/vim-nomtime.pl'れ、.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->{$_}, $_;
    }
}

いくつかの優れた機能:

  • 複数のファイル名をサポート

  • 複数の「監視」ディレクトリをサポート

  • シンボリックリンクされたディレクトリをサポート

  • 他の基準で強化できます

そのほとんどはおそらく純粋なvimバージョンでも実現できます。希望するpure-vimソリューションと比較した場合のこのソリューションの欠点は次のとおりです。

  • vimが終了した後にのみスタンプを復元するため、長い編集を行って定期的に保存すると、vimを終了するまでファイルは「ポップアップ」として新規作成されます

  • コマンドラインで複数のファイルをサポートしますが、非常に単純な方法@ARGVで、ファイルがファイルであるかどうかのみをチェックします。これはおそらくワイルドカード(例vim note-*.txt)やその他の面白いものでは動作しません。

  • それはクラッシュプルーフではなく、おそらくHUPプルーフでもありません(それは可能です)

  • ...まあ、それはラッパーです。(つまり、ラッパーを使用してすべてを解決した場合、何か悪いことが起こる前にいくつのラッパーを持っているでしょうか?)


2019年5月3日、2017年11月11日からファイルを変更しましたが、変更が加えられ、元のタイムスタンプが保持されます。:)
jmort253

1

この短いスクリプトは、ファイルの親ディレクトリにファイルが含まれている場合、変更された時間を保持し.nomtimeます。

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

1

このbash機能を試してください(ShâuShắcの答え基づいて

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

これを使用してファイルを編集し、変更された時間を保存できます

vi-preserve-time file1.txt file2.txt

(1)これは、5年前のShâuShắcの回答とほとんど同じです。(2)これは、ユーザーがvi一度に1つのファイルのみを呼び出すことを前提としています。動作しませんvi file1 file2。(3)言うまでもなく、ユーザーがで別のファイルに切り替えた場合、:e処理されません。
G-Manは「Reinstate Monica」と言います

参照するのを忘れてすみません、今、ShâuShắcの答えへの参照リンクを追加しました。
スティーリーウィング

あなたの質問#3について、コマンドラインに別のファイルを開いていない場合、それはあなたの問題だと思います。
スティーリーウィング

1
私のポイントは、質問が「どうやってvimを自分の思うように振る舞わせることができますか?」回答。OK、多分私のコメントは少し不公平です。他のすべての答えには同じ制限があるようで、私が知る限り、誰もそれについて言及していません。私はあなたの答えを見直していました。それは新しいからです。他の答えを見るのに多くの時間を費やしませんでした。
G-Manは「Reinstate Monica」と言います

1

別のファイルからタイムスタンプをコピーするオプションがあります。

touch -m -r file_source file_target

例:

[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

1

このWebページで、既存の変更時間を保持しながら現在のファイルを保存するvim関数を作成し、この関数をF4ファンクションキーにバインドする優れたソリューションを見つけました 。

ただし、F4変更時間の変更時にvimが混乱するため、元の関数に小さなバグが含まれており、同じファイルで2回使用すると次の警告がトリガーされることがわかりました。

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

幸いなことに、これは簡単に修正できます。タイムスタンプを復元した後にファイルをリロードする「編集」コマンドを元の関数に追加しました。

以下は、このバグ修正で修正されたvim関数であり、以下に追加できます~/.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>

注:この関数はdatestatおよびのGNUバージョンに依存していますtouch


0

上記の概念のいくつかを使用して、この目的で「編集」コマンドを使用可能にするCSHの非常に迅速でダーティな1ライナーエイリアスを次に示します。

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

"vim"の代わりに$ VISUALまたは$ EDITOR環境変数を簡単に使用できます。この方法では、次のコマンドを発行してデフォルトのエディターを変更できます

setenv VISUAL nano

エイリアス自体は、さまざまなエディタに対応するために再定義する必要がないため、多少移植性が高くなります。もちろん、CSHまたはTCSH以外のシェルを使用する場合、上記の例を適宜変更できます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.