Redaktorzy mogą stosować kilka strategii zapisywania pliku. Dwa główne warianty to zastąpienie istniejącego pliku lub zapisanie nowego pliku i przeniesienie go na miejsce. Zapisywanie do nowego pliku i przenoszenie go na miejsce ma przyjemną właściwość, która w dowolnym momencie czytania z pliku daje pełną wersję pliku (jedna chwila stara, druga chwila nowa). Jeśli plik zostanie nadpisany w miejscu, istnieje czas, w którym jest niekompletny, co jest problematyczne, jeśli jakiś inny program uzyskuje do niego dostęp właśnie wtedy lub gdy system ulega awarii.
Nano najwyraźniej nadpisuje istniejący plik. Twój skrypt wykrywa moment, w którym kończy pisanie ( close_write
zdarzenie) i uruchamia się rsync
w tym momencie. Zauważ, że rsync może pobrać niepełną wersję pliku, jeśli zapiszesz dwa razy z rzędu, zanim rsync zakończy swoje zadanie od pierwszego zapisu.
Z drugiej strony Vim stosuje strategię zapisu i przeniesienia - coś z tego wynika
echo 'new content' >somefile.new
mv -f somefile.new somefile
Stara wersja pliku zdarza się, że zostaje on usunięty w miejscu, w którym nowa wersja jest przenoszona na miejsce. W tym momencie inotifywait
polecenie powraca, ponieważ plik, który kazano obejrzeć, już nie istnieje. (Nowy somefile
to inny plik o tej samej nazwie.) Gdyby Vim został skonfigurowany do tworzenia pliku kopii zapasowej, to co by się stało, to coś w rodzaju
echo 'new content' >somefile.new
ln somefile somefile.old
mv -f somefile.new somefile
i inotifywait
będzie teraz oglądać kopię zapasową.
Aby uzyskać więcej informacji na temat strategii zapisywania plików, zobacz Jak można wykonać aktualizację na żywo podczas działania programu? oraz Uprawnienia do plików i zapisywanie
Vimowi można polecić użycie strategii zastępowania: wyłącz backupcopy
opcję ( :set nobackupcopy
). Jest to ryzykowne, jak wskazano powyżej.
Aby obsłużyć obie strategie zapisu, obejrzyj katalog i filtruj zarówno zdarzenia, jak close_write
i moved_to
zdarzenia somefile
.
inotifywait -m -e close_write,moved_to --format %e/%f . |
while IFS=/ read -r events file; do
if [ "$file" = "somefile" ]; then
…
fi
done