题
当之前的 Vim 会话崩溃时,您会看到“交换文件...已经存在!”对于上一个会话中打开的每个文件。
你能让这个 Vim 恢复提示变得更智能吗?(无需关闭恢复!)具体来说,我正在考虑:
- 如果交换的版本不包含未保存的更改并且编辑过程不再运行,你能让Vim自动删除交换文件吗?
- 您能否自动执行建议的过程,以新名称保存恢复的文件,将其与磁盘上的文件合并,然后删除旧的交换文件,以便需要最少的交互?特别是当交换版本和磁盘版本相同时,一切都应该是自动的。
我发现了 SwapExists
自动命令,但我不知道它是否可以帮助完成这些任务。
解决方案
我让 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 窗口中显示,以便我可以合并未保存的更改。
——乔瑟
其他提示
我刚刚发现这个:
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
很棒的提示 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
可能可以使用更多的错误检查和引用,但到目前为止已经有效。
我不想在 .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
我的 .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
但我没有时间正确测试它。
希望能帮助到你。
查找 ./ -type f -name ".*sw[klmnop]" -delete
信用:@Shwaydogghttps://superuser.com/questions/480367/whats-the-easiest-way-to-delete-vim-swapfiles-ive-already-recovered-from
首先导航到目录