更智能的Vim恢复?

时间:2008-09-15 13:57:47

标签: vim recovery

当之前的Vim会话崩溃时,您会看到“交换文件......已经存在!”对于在上一个会话中打开的每个文件。

你能让这个Vim恢复提示更聪明吗? (没有关闭恢复!)具体来说,我在考虑:

  • 如果交换的版本不包含未保存的更改且编辑过程不再运行,您是否可以让Vim自动删除交换文件?
  • 您是否可以自动执行以新名称保存恢复文件的建议过程,将其与磁盘上的文件合并,然后删除旧的交换文件,以便最小化交互?特别是当交换版本和磁盘版本相同时,一切都应该是自动的。

我发现了SwapExists自动命令,但我不知道它是否可以帮助完成这些任务。

7 个答案:

答案 0 :(得分:36)

我有vim将我的交换文件存储在一个本地目录中,在我的.vimrc中有这个:

set directory=~/.vim/swap,.

除了其他好处之外,这使得交换文件很容易一次找到。 现在,当我的笔记本电脑失去电源或其他任何东西时,我开始备份一堆交换文件,我只是运行我的cleanswap脚本:

TMPDIR=$(mktemp -d) || exit 1
RECTXT="$TMPDIR/vim.recovery.$USER.txt"
RECFN="$TMPDIR/vim.recovery.$USER.fn"
trap 'rm -f "$RECTXT" "$RECFN"; rmdir "$TMPDIR"' 0 1 2 3 15
for q in ~/.vim/swap/.*sw? ~/.vim/swap/*; do
  [[ -f $q ]] || continue
  rm -f "$RECTXT" "$RECFN"
  vim -X -r "$q" \
      -c "w! $RECTXT" \
      -c "let fn=expand('%')" \
      -c "new $RECFN" \
      -c "exec setline( 1, fn )" \
      -c w\! \
      -c "qa"
  if [[ ! -f $RECFN ]]; then
    echo "nothing to recover from $q"
    rm -f "$q"
    continue
  fi
  CRNT="$(cat $RECFN)"
  if diff --strip-trailing-cr --brief "$CRNT" "$RECTXT"; then
      echo "removing redundant $q"
      echo "  for $CRNT"
      rm -f "$q"
  else
      echo $q contains changes
      vim -n -d "$CRNT" "$RECTXT"
      rm -i "$q" || exit
  fi
done

这将删除与真实文件保持同步的所有交换文件。任何不匹配的都会在vimdiff窗口中显示,因此我可以合并我未保存的更改。

- 欺骗专家

答案 1 :(得分:20)

我刚刚发现了这个:

http://vimdoc.sourceforge.net/htmldoc/diff.html#:DiffOrig

我将DiffOrig命令复制并粘贴到我的.vimrc文件中,它就像一个魅力。这大大简化了交换文件的恢复。我不知道为什么它默认不包含在VIM中。

这是针对那些赶时间的人的命令:

 command DiffOrig vert new | set bt=nofile | r # | 0d_ | diffthis
    \ | wincmd p | diffthis

答案 2 :(得分:16)

接受的答案是针对一个非常重要的用例。假设您创建了一个新的缓冲区并输入了2个小时而没有保存,那么您的笔记本电脑崩溃了。如果您运行建议的脚本,它将删除您的唯一记录,.swp交换文件。我不确定什么是正确的修复,但看起来diff命令最终在这种情况下将相同的文件与自身进行比较。下面编辑的版本会检查这种情况,并为用户提供在某处保存文件的机会。

#!/bin/bash

SWAP_FILE_DIR=~/temp/vim_swp
IFS=$'\n'

TMPDIR=$(mktemp -d) || exit 1
RECTXT="$TMPDIR/vim.recovery.$USER.txt"
RECFN="$TMPDIR/vim.recovery.$USER.fn"
trap 'rm -f "$RECTXT" "$RECFN"; rmdir "$TMPDIR"' 0 1 2 3 15
for q in $SWAP_FILE_DIR/.*sw? $SWAP_FILE_DIR/*; do
  echo $q
  [[ -f $q ]] || continue
  rm -f "$RECTXT" "$RECFN"
  vim -X -r "$q" \
      -c "w! $RECTXT" \
      -c "let fn=expand('%')" \
      -c "new $RECFN" \
      -c "exec setline( 1, fn )" \
      -c w\! \
      -c "qa"
  if [[ ! -f $RECFN ]]; then
    echo "nothing to recover from $q"
    rm -f "$q"
    continue
  fi
  CRNT="$(cat $RECFN)"
  if [ "$CRNT" = "$RECTXT" ]; then
      echo "Can't find original file. Press enter to open vim so you can save the file. The swap file will be deleted afterward!"
      read
      vim "$CRNT"
      rm -f "$q"
  else if diff --strip-trailing-cr --brief "$CRNT" "$RECTXT"; then
      echo "Removing redundant $q"
      echo "  for $CRNT"
      rm -f "$q"
  else
      echo $q contains changes, or there may be no original saved file
      vim -n -d "$CRNT" "$RECTXT"
      rm -i "$q" || exit
  fi
  fi
done

答案 3 :(得分:4)

伟大的提示DiffOrig是完美的。这是一个bash脚本,用于在当前目录下的每个交换文件上运行它:

#!/bin/bash

swap_files=`find . -name "*.swp"`

for s in $swap_files ; do
        orig_file=`echo $s | perl -pe 's!/\.([^/]*).swp$!/$1!' `
        echo "Editing $orig_file"
        sleep 1
        vim -r $orig_file -c "DiffOrig"
        echo -n "  Ok to delete swap file? [y/n] "
        read resp
        if [ "$resp" == "y" ] ; then
                echo "  Deleting $s"
                rm $s
        fi
done

可能会使用更多错误检查和引用,但到目前为止已经有效。

答案 4 :(得分:0)

我更喜欢不在.vimrc中设置我的VIM工作目录。这是对chouser脚本的修改,它根据需要检查重复项将交换文件复制到交换路径,然后协调它们。这是匆忙写的,请务必在将其投入实际使用之前对其进行评估。

#!/bin/bash

if [[ "$1" == "-h" ]] || [[ "$1" == "--help" ]]; then
   echo "Moves VIM swap files under <base-path> to ~/.vim/swap and reconciles differences"
   echo "usage: $0 <base-path>"
   exit 0
fi

if [ -z "$1" ] || [ ! -d "$1" ]; then
   echo "directory path not provided or invalid, see $0 -h"
   exit 1
fi

echo looking for duplicate file names in hierarchy
swaps="$(find $1 -name '.*.swp' | while read file; do echo $(basename $file); done | sort | uniq -c | egrep -v "^[[:space:]]*1")"
if [ -z "$swaps" ]; then
   echo no duplicates found
   files=$(find $1 -name '.*.swp')
   if [ ! -d ~/.vim/swap ]; then mkdir ~/.vim/swap; fi
   echo "moving files to swap space ~./vim/swap"
   mv $files ~/.vim/swap
   echo "executing reconciliation"
   TMPDIR=$(mktemp -d) || exit 1
   RECTXT="$TMPDIR/vim.recovery.$USER.txt"
   RECFN="$TMPDIR/vim.recovery.$USER.fn"
   trap 'rm -f "$RECTXT" "$RECFN"; rmdir "$TMPDIR"' 0 1 2 3 15
   for q in ~/.vim/swap/.*sw? ~/.vim/swap/*; do
     [[ -f $q ]] || continue
     rm -f "$RECTXT" "$RECFN"
     vim -X -r "$q" \
         -c "w! $RECTXT" \
         -c "let fn=expand('%')" \
         -c "new $RECFN" \
         -c "exec setline( 1, fn )" \
         -c w\! \
         -c "qa"
     if [[ ! -f $RECFN ]]; then
       echo "nothing to recover from $q"
       rm -f "$q"
       continue
     fi
     CRNT="$(cat $RECFN)"
     if diff --strip-trailing-cr --brief "$CRNT" "$RECTXT"; then
         echo "removing redundant $q"
         echo "  for $CRNT"
         rm -f "$q"
     else
         echo $q contains changes
         vim -n -d "$CRNT" "$RECTXT"
         rm -i "$q" || exit
     fi
   done
else
   echo duplicates found, please address their swap reconciliation manually:
   find $1 -name '.*.swp' | while read file; do echo $(basename $file); done | sort | uniq -c | egrep '^[[:space:]]*[2-9][0-9]*.*'
fi

答案 5 :(得分:0)

我的.bashrc文件中有这个。我想对这部分代码给予适当的评价,但我忘了从哪里得到它。

mswpclean(){

for i in `find -L -name '*swp'`
do
    swpf=$i
    aux=${swpf//"/."/"/"}
    orif=${aux//.swp/}
    bakf=${aux//.swp/.sbak}

    vim -r $swpf -c ":wq! $bakf" && rm $swpf
    if cmp "$bakf" "$orif" -s
    then rm $bakf && echo "Swap file was not different: Deleted" $swpf
    else vimdiff $bakf $orif
    fi
done

for i in `find -L -name '*sbak'`
do
    bakf=$i
    orif=${bakf//.sbak/}
    if test $orif -nt $bakf
    then rm $bakf && echo "Backup file deleted:" $bakf
    else echo "Backup file kept as:" $bakf
    fi
done }

我只是在项目的根目录上运行它,如果文件不同,它会打开vim diff。然后,将保留要保存的最后一个文件。为了使它完美,我只需要替换最后的其他内容:

else echo "Backup file kept as:" $bakf

类似

else vim $bakf -c ":wq! $orif" && echo "Backup file kept and saved as:" $orif

但是我没有时间对它进行适当的测试。

希望它有所帮助。

答案 6 :(得分:0)

find ./ -type f -name“。* sw [klmnop]”-delete

信用:@Shwaydogg https://superuser.com/questions/480367/whats-the-easiest-way-to-delete-vim-swapfiles-ive-already-recovered-from

首先导航到目录