4

在 Snow Leopard 中,每当用户在 Finder 中复制目录时,我想触发脚本/代码。我怎样才能做到这一点?

我一直在寻找文档,但我对这类工作有点太新了,无法识别正确的方法。

动机:如果一个目录处于版本控制之下,比如 git、hg 或 svn,并且用户复制了该目录,那么我想运行一个脚本来搜索原始目录,然后在版本控制中创建一个“标签”。如果用户重命名目录,比如在 10 秒内,那么重命名将成为该标签注释的一部分。我最终还想添加一些覆盖图标来指示目录的版本控制状态。

扩展动机:我面临的问题是版本控制软件,如 git 和 hg,在我看来太复杂了,即因为它与文件系统太断开,并且充当某种影子文件系统。我是版本控制的忠实拥护者,并且已经使用了很多年——但我也看到了部署的局限性,因为它的复杂性。现实情况是,如果更易于使用,将会有更多代码处于版本控制之下。

我正在研究创建一个不需要终端访问的更易于使用的 VCS 系统的可行性。想象一下,如果 Apple 将其作为 finder 和/或 iLife 的一部分,版本控制(代码)会是什么样子——简单但足够好。实际上,我显然不会重新发明 vcs,但我希望为 hg 之类的东西构建一个模块/插件,并将其与重新设想 vcs 如何用于以查找器为中心的 UI 结合起来a - 全部为更休闲的程序员创建一个更简单但足够好的 VCS。

检测目录复制和重命名的第一个技术障碍 - 因此这个问题。

文件数量:由于这个项目的主要动机是源代码版本控制,我只需要匹配与您正在处理的项目数量相匹配的目录数量。所以,如果你正在处理两个不同的项目,那么我认为我只需要跟踪两个目录——每个项目的根目录。现在,我完全承认,在这一点上,我可能错误地描述了需求,所以也许我需要跟踪项目中的所有目录,或者甚至这些项目中的所有文件,所以让我们说,为了争论,一个典型的项目中有 1,000 个文件。所以,基本上,可能只有几个目录,或者几百个目录,或者几千个文件。重要的是,我认为50,000 个文件将处于频谱的高端。

用户从查找器中复制目录“主干”

主干 --> 主干副本

如果用户将 'trunk copy' 重命名为 'trunk copy fixed #255 per colours',trunk 目录(不是副本)将被标记为注释 'fixed #255 per colour'

参考资料

  • 文件系统事件编程

    • 如果注册目录中的某些内容发生更改,则在启动时获得通知- 如果大目录中的任何一个文件发生更改。它不会告诉你,我不认为,发生了什么变化。
  • 内核队列

    • 您可以注册以获取单个文件级别的通知。您的选择(至少)如下: NOTE_DELETE | NOTE_WRITE | 注意_EXTEND | NOTE_ATTRIB | 注意_LINK | 注意_重命名 | NOTE_REVOKE 这可能用于检测目录重命名(它适用于 dirs 吗?),但显然不是 dir 副本。

稍微相关的问题

谢谢,JJ

4

4 回答 4

3

最初的帖子提出了一个非常大的项目,其中包含许多未指定的功能。您以“...检测目录副本和重命名...”结尾的“扩展动机”很有帮助。

首先,您几乎用文件系统事件和内核队列的引用回答了您自己的帖子。您解雇文件夹操作是正确的,但原因是错误的。您似乎关心为大量文件夹激活 FA。这不是问题,因为它可以自动化。FA 不起作用的原因是它们无法检测到文件重命名。此外,由于操作是 AppleScript,因此开销和并发性存在巨大问题。

你对 FS 事件是正确的:(来自Darwin Docs

重要的一点是通知的粒度是在目录级别。它只告诉您目录中的某些内容发生了变化,但不告诉您发生了什么变化。

所以看来你只剩下内核队列了。他们什么都做。请注意,您必须聪明地使用内核队列 - 您必须知道苍蝇的名称才能监控它。因此,在创建新文件/文件夹时,您必须解释事件并打开 (O_EVTONLY) 新文件。但是,有一个问题:(更多Darwin Docs

但是,如果您正在监视大量的内容层次结构,则应该使用文件系统事件,因为内核队列比内核事件稍微复杂一些,并且由于涉及到额外的用户内核通信,因此可能会占用更多资源。

Another reply had mentioned that TimeMachine used FS Events. I doubt that because of the noted 'coarse granularity'. I suspect that there is a special hook in the kernel 'close file' code. At least, that is what it seems you need if you want to monitor many files. How many are you considering?

于 2010-01-18T22:13:24.070 回答
2

听起来文件系统事件就是您想要的。也许你会回避它,因为它看起来很复杂,但我认为你想要做的事情总的来说很复杂。

Spotlight 和 Time Machine 使用文件系统事件来确定文件系统中发生了什么变化,从而确定需要索引或备份哪些文件。您的要求类似,只是您不想备份,而是要检查更新的目录是否存在于源代码管理中,如果不存在,则确定是否应将某些内容(新目录或标签或其他)添加到源代码管理中。

可能有一种方法可以在 Finder 中执行此操作,但您可能还想知道用户是从命令行复制目录还是从其他程序复制目录。

您能否详细介绍一下您使用此功能的动机?听起来您正在尝试让用户“使用”源代码控制,而无需实际学习它。“只需复制目录,集成代码将处理一切。” 但我认为你会在尝试将非常一般的文件系统更改解释为隐式源代码控制命令时遇到问题。

于 2010-01-16T12:22:53.197 回答
1

如果您只想在某些文件夹上触发此脚本,那么您应该使用 Apple 所谓的“文件夹操作”,您可以将其附加到您喜欢的任何文件夹中的 Apple 脚本。

我不知道 Finder 会触发什么,但如果我有我的 mac,我知道我会打开自动器并在“文件和文件夹”下查看我 100% 你会在那里找到一个复制或复制的事件。

于 2010-01-13T01:38:40.937 回答
1

在自动机脚本中没有来自查找器/系统的“重复”和“重命名”事件,所以您所要求的正是需要使用文件系统事件(我不会进入),但下面的快速applescript

  • 捕获添加到文件夹中的所有项目(包括通过重复添加的项目)
  • 要求用户提供标签名称
  • 使用此信息运行 bash 脚本

这应该使您能够构建一个好的解决方案

  1. 将 additem.scpt 放在 /Library/Scripts/Folder Action Scripts
  2. fixup.sh 在包含主干的文件夹中(或调整并放在你喜欢的地方)
  3. 在包含的文件夹上,右键单击并选择“文件夹操作设置...”
  4. 用新脚本连接文件夹
  5. 编辑 fixup.sh 以满足您的需要

additem.scpt

on adding folder items to this_folder after receiving added_items
        try
                tell application "Finder"
                        set the folder_name to the name of this_folder
                end tell

                set the item_count to the number of items in the added_items

                repeat with an_added_item in added_items
                        tell application "Finder"
                                set item_name to name of an_added_item
                        end tell

                        set new_name to text returned of (display dialog "Please enter tag name " default answer item_name buttons {"Continue…"} default button 1)

                        set the scriptcode to "\"" & POSIX path of this_folder & "fixup.sh\" \"" & POSIX path of an_added_item & "\" \"" & new_name & "\""
                        display dialog scriptcode
                        do shell script scriptcode
                end repeat
        end try
end adding folder items to

修复.sh

#!/bin/bash

if [ -d "$1" ]
then
  echo asked to fixup \"$1\" >> /tmp/fixup.log
fi
于 2010-01-16T20:40:58.253 回答