如何记录对特定文件夹的访问及其内容的更改?

如何记录对特定文件夹的访问及其内容的更改?

我需要跟踪文件夹访问时间,并想知道对其进行了哪些更改。

我如何触发这些事件?有没有办法在打开文件夹时运行特定的 .sh 文件?

答案1

我假设你需要知道文件夹打开的(时钟)时间,例如鹦鹉螺,而不是需要的时间访问该文件夹。

使用窗口列表

您可以从命令中获取窗口列表wmctrl -l,并查看文件夹的名称是否出现在列表中。但是,检查循环至少需要一瞬间才能注意到文件夹已打开。

您必须wmctrl安装:

sudo apt-get install wmctrl

在下面的示例中,脚本在第一次访问文件夹时运行一个命令,然后退出。

如何使用:

  • 将脚本粘贴到空文件中
  • 另存为access_time.py
  • "<command_to_run>"通过命令更改脚本的头部部分(引号之间)
  • 使用以下命令运行它:

    python3 </path/to/script> <foldername_without_path>
    

    或者,如果你使它可执行:

    </path/to/access_time.py> <foldername_without_path>
    
#!/usr/bin/env python3
import subprocess
import sys
#--- replace "<command_to_run>" with your command (between quotes):
command = "<command_to_run>"
#---
foldername = sys.argv[1]
while True:
    try:
        test = subprocess.check_output(["wmctrl", "-l"]).decode("utf-8")
    except subprocess.CalledProcessError:
        pass
    if foldername in test:
        subprocess.call(["/bin/bash", "-c", command])
        break

编辑

但是您可以使其“一体式”运行,这样您就不需要另一个脚本了。下面的脚本会在您的 $HOME 目录中创建一个文件,其中包含访问文件夹的时间。:

#!/usr/bin/env python3
import subprocess
import sys
import os
import time
home = os.environ["HOME"]
foldername = sys.argv[1]

#--- the path your file is saved to (change if you want to, but use full paths)
path = home
#---

while True:
    try:
        test = subprocess.check_output(["wmctrl", "-l"]).decode("utf-8")
    except subprocess.CalledProcessError:
        pass
    if foldername in test:
        with open(path+"/time_data.txt", "a") as out:
            out.write("the folder "+foldername+" was opened "+time.ctime()+"\n")
        break
  • 像第一个选项一样使用它(但显然你不需要设置命令)
  • 在文件名前放置一个点可使其成为隐藏文件(按Ctrl+H可切换可见性):

    如果您想要这样,请更改:

    with open(path+"/time_data.txt", "a") as out:
    

    进入:

    with open(path+"/.time_data.txt", "a") as out:
    

    (注意缩进!)

编辑2

从您的评论和聊天中的讨论中,我了解到您实际上正在寻找一种工具来记录对文件夹的访问(例如通过 nautilus)及其内容的更改。
作为额外的选项,一个全面的日志脚本可以在两个不同的线程中记录:

  • 所有情况下,文件夹都被 nautilus 等访问过,并记录在文件中access_log.txt
  • 所有文件夹窗口关闭的情况,也登录了access_log.txt
  • 所有添加到(递归)或从目录中删除的文件都记录到文件中directory_log.txt

这些事件被记录在两个不同的文件中,因为日志的刷新时间不同。实时“记录”一个包含大量子目录的大型目录发生的事情并不是您希望每 5 秒左右完成一次的事情。结果是:

  • 使用权日志的精度为 0.5 秒(我是这样设置的)
  • 目录log(添加/删除文件)的精度为 10 分钟。事件将在发生后 10 分钟内报告,时间戳精度为 10 分钟。

    我在一个约 800 GB 的(网络)目录上进行了测试。如果你的目录小得多,目录log-cycle 也可以 (小得多)。例如,我在 20 GB 的目录上进行了测试,其 (目录日志) 周期为 10 秒。

示例输出access_log.txt:

---------------Thu Feb 19 21:01:09 2015---------------
folder opened

---------------Thu Feb 19 21:01:27 2015---------------
folder closed

示例输出 directory_log.txt:

---------------Thu Feb 19 21:14:24 2015---------------
+ /home/jacob/Afbeeldingen/Downloads/2023.pdf
- /home/jacob/Afbeeldingen/Downloads/History-journal
- /home/jacob/Afbeeldingen/Downloads/google-earth-stable_current_i386.deb

剧本:

  • 按照上面的脚本进行设置但有一个重要的区别

    • 而不是使用文件夹姓名作为争论,设置完整的小路+脚本头部的文件夹名称(参见脚本中的示例)
  • 运行它的命令是:

    python3 /path/to/script.py
    
#!/usr/bin/env python3
import subprocess
import os
import time
import difflib
from threading import Thread
home = os.environ["HOME"]

# The folder to watch:
folder = "/home/jacob/Afbeeldingen"
# the path your log files are saved to (change if you want to, but use full paths):
path = home
#---

for f in os.listdir(path):
    if f.startswith("dr_check_"):
        os.remove(path+"/"+f)

dr_data = path+"/directory_log.txt"
access_data = path+"/access_log.txt"

for f in [dr_data, access_data]:
    if not os.path.exists(f):
        subprocess.Popen(["touch", f])       
foldername = folder.split("/")[-1]

def check_windowlist(foldername):
    while True:
        try:
            if foldername in subprocess.check_output(["wmctrl", "-l"]).decode("utf-8"):
                return "folder opened\n"
            else:
                return "folder closed\n"
            break
        except subprocess.CalledProcessError:
            pass

def check_directory(directory, outfile):
    with open(outfile, "wt") as out:
        for root, dirs, files in os.walk(directory):
            for f in files:
                out.write(root+"/"+f+"\n")

def run_accesscheck():
    while True:
        ch1 = check_windowlist(foldername)
        time.sleep(0.5)
        ch2 = check_windowlist(foldername)
        if ch1 != ch2:
            with open(access_data, "a") as out:
                out.write("-"*15+time.ctime()+"-"*15+"\n"+ch2+"\n")

def run_directorycheck():
    last = 1; outfile_name = "dr_check_"; last_outfile = ""
    while True:
        outfile = path+"/"+outfile_name+str(last)+".txt"
        check_directory(folder, outfile)
        if last != 1:
            changes = []
            diff = difflib.ndiff(
                open(last_outfile).readlines(),
                open(outfile).readlines()
                )
            for item in diff:
                if item.startswith("-") or item.startswith("+"):
                    changes.append(item)
            if len(changes) > 0:
                with open(dr_data, "a") as out:
                    out.write("-"*15+time.ctime()+"-"*15+"\n")
                    for it in sorted(changes):
                        out.write(it)
                    out.write("\n")
            os.remove(last_outfile)       
        last_outfile = outfile; last = last+1
        time.sleep(600)

Thread(target = run_directorycheck).start()
Thread(target = run_accesscheck).start()

答案2

如果你想使用 Bash 而不是 Python:

#!/bin/bash
folder=$1
while true;
do
    command=$(wmctrl -l | grep -o "$folder")
    if [[ "$folder" == "$command" ]];
    then
        ./myscript.sh
        break;
    fi
done

编辑:

我更改了一个脚本,以便您可以使用以下命令运行它:

bash folderwatch.sh BackupSSD

另外,您可以使脚本可执行,这样您就可以在没有 sh 或 bash 的情况下使用它,因为 shell 是在脚本的第一行定义的,例如:

chmod u+x folderwatch.sh
./folderwatch.sh BackupSSD

答案3

sudo apt-get incron安装“inotify cron”系统

http://inotify.aiken.cz/?section=incron&page=about&lang=en

echo $USER | sudo tee --append /etc/incron.allow让您可以玩游戏。

icrontab -e创建要观看的事件。它将打开nano

输入你的内心渴望。例如,

/home/nodak/watched_dir IN_ACCESS /home/nodak/bin/personal.sh

保存并测试。

更多信息来自http://manpages.ubuntu.com/manpages/saucy/man5/incrontab.5.html

虽然它看起来很简单,但复杂动作的语法并不完全相同常规的重击,cf,https://stackoverflow.com/questions/23706194/using-zenity-in-a-root-incron-job-to-display-message-to-currently-logged-in-user

相关内容