Как я могу заставить скрипт запускаться при удалении файла?
У меня есть приложение, которое сохраняет свои данные в виде "рабочих файлов" XML, которые содержат списки гораздо больших файлов.tif, которые содержат фактические необработанные данные, которые генерирует приложение. Как правило, пользователь приложения заботится только о местонахождении файла задания XML: если он будет перемещен или переименован, список файлов.tif останется действительным, поскольку полный путь к ним (который часто будет на удаленном диске) выделенный для этой цели) записывается внутри файла таким образом, что является прозрачным для пользователя. Делая так, рабочий файл может быть небольшим, а не раздуваться до десятков гигабайт.
Однако если пользователь решит удалить файл задания из ОС (то есть из окна cmd или проводника Windows в Windows, или из оболочки bash или Nautilus в Linux), существует опасность возникновения хаоса из-за связи между рабочий файл и данные его изображения будут разделены. Файлы изображений, связанные с файлом задания, будут "осиротевшими", более не доступны из приложения, но, тем не менее, по-прежнему занимают место на диске.
Было бы достаточно легко написать сценарий оболочки, который будет анализировать XML-файл, идентифицировать файлы изображений, которые перечислены в нем, и удалять их. Если этот сценарий оболочки будет запускаться автоматически всякий раз, когда пользователь удаляет файл, это решит мою проблему одним махом. Однако я абсолютно не представляю, как настроить ОС так, чтобы она запускала скрипт при удалении файла, либо в Windows, либо в Linux.
Есть ли способ сделать это?
1 ответ
В Linux вы можете использовать простой скрипт bash, подобный следующему:
#!/bin/bash
# Run code before and after prompting a user to delete a file
my_rm=/bin/rm
file1=$1
# Put the code you want to run pre-deletion here:
echo Running code before deleting ${file1}.
# Delete the file.
read -p "Are you sure you want to delete ${file1} (y/N): " decision
if [ "$decision" == "Y" ] || [ "$decision" == "y" ]; then
echo Deleting ${file1}...
$my_rm $file1
# Put the code you want to run post-deletion here:
echo Running code after deleting ${file1}.
else
echo No file deleted.
fi
# Put any cleanup code here:
echo Running cleanup code whether or not ${file1} was deleted.
exit
Предполагая, что вы вызываете скрипт my-delete.sh, вы сделаете его исполняемым,
chmod +x my-delete.sh
и запустить его так:
my-delete.sh jobfile.xml
Теперь, если вы хотите использовать rm
чтобы удалить файлы, вы можете псевдоним rm
к сценарию:
alias rm='/path/to/my-delete.sh'
Добавьте предыдущую строку в ваш ~/.bashrc или ~/.profile или где угодно для вашей системы, чтобы сделать ее постоянной.
Если вы не хотите запускать дополнительный код для файлов, отличных от ваших файлов заданий, вы можете добавить тест для имени файла или типа файла и запускать дополнительный код только для этих файлов. Следующий скрипт помещает специальный код в функцию, а затем проверяет имя файла, чтобы увидеть, содержит ли он шаблон "файл задания".
#!/bin/bash
# Run code before and after prompting a user to delete a file
my_rm=/bin/rm
file1=$1
pattern='jobfile'
function rm_jobfile () {
# Put the code you want to run pre-deletion here:
echo Running code before deleting ${file1}.
# Delete the file.
read -p "Are you sure you want to delete ${file1} (y/N): " decision
if [ "$decision" == "Y" ] || [ "$decision" == "y" ]; then
echo Deleting ${file1}...
$my_rm $file1
# Put the code you want to run post-deletion here:
echo Running code after deleting ${file1}.
else
echo No file deleted.
fi
# Put any cleanup code here:
echo Running cleanup code whether or not ${file1} was deleted.
}
# If the file is a jobfile, run the function, otherwise just delete it.
if [[ $file1 =~ $pattern ]]; then
rm_jobfile $file1
else
$my_rm $file1
fi
exit
Предполагая, что вы создали псевдоним, описанный выше, запустив
rm jobfile1.xml
выполнит код функции в my-delete.sh, но работает
rm something.txt
не будет.
Поскольку Microsoft Windows теперь включает в себя bash (и, как мне кажется, ядро Linux), он также должен работать там, но я его не проверял. Я уверен, что сценарий powershell может быть адаптирован из этого также. Я не парень из Windows. Надеюсь это поможет.
Есть порт Windows inotifywait
как уже упоминалось в комментариях под названием inotify-win
Скачать:
https://github.com/thekid/inotify-win/archive/master.zip
Обобщение:
%WINDIR%\Microsoft.NET\Framework\v4.0.30319\csc.exe /t:exe /out:inotifywait.exe src\*.cs
Использование:
$ inotifywait.exe
Usage: inotifywait [options] path [...]
Options:
-r/--recursive: Recursively watch all files and subdirectories inside path
-m/--monitor: Keep running until killed (e.g. via Ctrl+C)
-q/--quiet: Do not output information about actions
-e/--event list: Events (create, modify, delete, move) to watch,
comma-separated. Default: all
--format format: Format string for output.
--exclude: Do not process any events whose filename matches the specified regex
--excludei: Ditto, case-insensitive
Formats:
%e : Event name
%f : File name
%w : Path name
%T : Current date and time
Редактировать:
Если вы хотите избежать злонамеренных действий, решение может быть icacls
в файловой системе NTFS
Чтобы защитить файл от удаления:
icacls file.ext /deny Everyone:(DE)
rem To reset
icacls file.ext /reset
Чтобы защитить папку с ее содержимым, используйте:
icacls folder /deny Everyone:(OI)(CI)(DE,DC)
rem To reset
icacls folder /reset
*S-1-1-0
вместо Everyone
также не зависит от языка %USERNAME%
для текущего пользователя.