Умнее восстановление Vim?

При сбое предыдущего сеанса Vim вы получаете сообщение «Файл подкачки ... уже существует!» для каждого файла, который был открыт в предыдущем сеансе.

Можете ли вы сделать эту подсказку восстановления Vim умнее? (Не отключая рекавери!) Конкретно я думаю о:

  • Если замененная версия не содержит несохраненных изменений и процесс редактирования больше не выполняется, можете ли вы заставить Vim автоматически удалить файл подкачки?
  • Можете ли вы автоматизировать предлагаемый процесс сохранения восстановленного файла под новым именем, слияния его с файлом на диске и последующего удаления старого файла подкачки, чтобы требовалось минимальное вмешательство? Особенно, когда версия подкачки и версия диска совпадают, все должно быть автоматически.

Я обнаружил автокоманду SwapExists, но не знаю, поможет ли она с этими задачами.


person Bruno De Fraine    schedule 15.09.2008    source источник


Ответы (7)


У меня 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, чтобы я мог объединить свои несохраненные изменения.

--Чоусер

person Chouser    schedule 15.09.2008
comment
Что, если вы отредактируете два файла с одинаковым именем, например, в двух ветках репозитория SVN? - person Nathan Fellman; 15.09.2008
comment
При редактировании более чем одного файла с одним и тем же именем Vim будет идти назад по алфавиту для расширений (.swp, *.swo, *.swn и т. д.). Следует отметить, что использование этого метода отключает функцию существования файла подкачки. Поэтому вам *нужно использовать приведенный выше скрипт cleanswap. - person matpie; 06.02.2009
comment
также см. ответ @coppit, который должен сохранять неписаные буферы? - person alxndr; 10.02.2013
comment
Для тех, кто работает с OSX: нашел github Chouser для этого (github.com/vim-scripts/cleanswap ), который у меня не работал, поэтому я разветвил его и внес улучшения: github.com/Kache/cleanswap< /а> - person Kache; 30.04.2013
comment
Этот скрипт не работает. Пробовал в папке проекта с кучей файлов подкачки, и ничего не удалил. - person Attila Szeremi; 19.11.2013
comment
Чтобы эта папка лучше работала с несколькими файлами с одинаковым именем, используйте суффикс //. Пример: set directory=~/.vim/swap//. С этой опцией vim создаст файлы подкачки, используя полный путь к каждому файлу. - person Juan Campa; 19.02.2014
comment
Это действительно не будет работать так же, как vim по умолчанию. На общих монтированиях, если ваш ноутбук выйдет из строя, а вы редактируете с другого устройства, файл подкачки будет недоступен для восстановления. Также возможно, что несколько пользователей случайно отредактируют один и тот же файл. - person WhyNotHugo; 21.04.2015

Я только что обнаружил это:

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

Я скопировал и вставил команду DiffOrig в свой файл .vimrc, и она отлично работает. Это значительно облегчает восстановление файлов подкачки. Я понятия не имею, почему он не включен по умолчанию в VIM.

Вот команда для тех, кто торопится:

 command DiffOrig vert new | set bt=nofile | r # | 0d_ | diffthis
    \ | wincmd p | diffthis
person Jack Senechal    schedule 21.10.2008
comment
Итак, после загрузки файла подкачки вы вызываете DiffOrig? - person Ehtesh Choudhury; 11.06.2011
comment
Да, поэтому, когда появится приглашение, вы нажимаете «восстановить», а затем набираете: DiffOrig. Затем, когда вы закончите, вы сохраните буфер. Затем, чтобы удалить файл подкачки (потому что в следующий раз он все еще будет задерживаться и вызывать проблемы), вы просто набираете: e, что снова вызывает приглашение, и вы можете нажать «Удалить». - person Jack Senechal; 07.07.2011
comment
Теперь это включено в Vim - person Juan Campa; 19.02.2014

Принятый ответ разорен для очень важного варианта использования. Допустим, вы создаете новый буфер и печатаете в течение 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
person coppit    schedule 29.04.2011
comment
Типа два часа без сохранения? Вам следует исправить свое отношение к сохранению, не принятому сценарию. Я автоматически сохраняюсь, когда делаю паузу, чтобы подумать. - person ZyX; 30.04.2011
comment
Будь то два часа или две секунды, молчаливая потеря данных неприемлема, и он был абсолютно прав, исправил это. Не нужно быть снисходительным. - person cecilkorik; 12.01.2012
comment
Опасность: если вы попытаетесь использовать этот сценарий для файлов .swp, не задав центральную директорию файла подкачки (например, изменив SWAP_FILE_DIR на .), он удалит многие из ваших файлов. Так что не делай этого. Или выньте $SWAP_FILE_DIR/* из петли for. - person Dan; 21.07.2014

Отличный совет 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

Вероятно, можно было бы использовать дополнительную проверку ошибок и цитирование, но пока это работает.

person Mark Grimes    schedule 24.04.2009
comment
Боже мой, как полезно и просто. Связан с set directory=~/.vim/swap,. и это прекрасно работает. - person Ehtesh Choudhury; 03.04.2013
comment
Хотя требуется несколько модификаций для поддержки других расширений подкачки, таких как swo|swn - person Ehtesh Choudhury; 30.04.2013

Я предпочитаю не устанавливать рабочий каталог VIM в файле .vimrc. Вот модификация сценария 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
person Mario Aguilera    schedule 24.05.2013

У меня есть это в моем файле .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

но у меня не было времени, чтобы как следует проверить это.

Надеюсь, поможет.

person Miguel    schedule 11.04.2014

find ./ -type f -name ".*sw[klmnop]" -delete

Кредит: @Shwaydogg https://superuser.com/questions/480367/whats-the-easisest-way-to-delete-vim-swapfiles-ive-already-recovered-from

Сначала перейдите в каталог

person user3386050    schedule 06.10.2016