Более разумное восстановление Vim?
Вопрос
Когда произошел сбой предыдущего сеанса Vim, вас приветствует сообщение "Файл подкачки ...уже существует!" для каждого файла, который был открыт в предыдущем сеансе.
Можете ли вы сделать это приглашение для восстановления Vim более умным?(Не отключая восстановление!) В частности, я имею в виду:
- Если замененная версия не содержит несохраненных изменений и процесс редактирования больше не выполняется, можете ли вы заставить Vim автоматически удалять файл подкачки?
- Можете ли вы автоматизировать предлагаемый процесс сохранения восстановленного файла под новым именем, объединения его с файлом на диске и последующего удаления старого файла подкачки, чтобы требовалось минимальное взаимодействие?Особенно, когда версия подкачки и версия диска совпадают, все должно быть автоматически.
Я обнаружил, что SwapExists
автокоманда, но я не знаю, может ли это помочь с этими задачами.
Решение
У меня есть vim, который хранит мои файлы подкачки в одном локальном каталоге, имея это в my .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, чтобы я мог объединить свои несохраненные изменения.
--Чоузер
Другие советы
Я только что обнаружил это:
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 часов, даже не сохраняя, затем ваш ноутбук выходит из строя.Если вы запустите предложенный скрипт это удалит вашу единственную запись - файл подкачки .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
Отличный совет, ДиффОриг идеален.Вот скрипт 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
Вероятно, не помешало бы еще немного проверить ошибки и привести цитаты, но до сих пор это работало.
Я предпочитаю не устанавливать свой рабочий каталог 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
У меня есть это в моем файле .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:
else echo "Backup file kept as:" $bakf
чем-то вроде
else vim $bakf -c ":wq! $orif" && echo "Backup file kept and saved as:" $orif
но у меня не было времени как следует это протестировать.
Надеюсь, это поможет.
найти ./ -введите f -имя ".*sw[klmnop]" - удалить
Кредит:@Швайдогг https://superuser.com/questions/480367/whats-the-easiest-way-to-delete-vim-swapfiles-ive-already-recovered-from
Сначала перейдите в каталог