【问题标题】:Applescript: How do I set a 'move to' folder based on the filename to sort files into Alphabetical folders?Applescript:如何根据文件名设置“移动到”文件夹以将文件排序到按字母顺序排列的文件夹中?
【发布时间】:2018-03-02 18:23:48
【问题描述】:

我正在尝试创建一个“文件夹操作”,它将根据文件名的第一个字母组织添加到每个字母表的子文件夹中的新文件。

我编写了以下代码,它可以将添加到子文件夹“A”中的所有内容作为起点,但现在我遇到了一个障碍。

on adding folder items to thisfolder after receiving added_items
repeat with i from 1 to number of items in added_items
    set this_item to (item i of added_items)
    set DestinationFolderName to "A"
    tell application "Finder"
        move this_item to folder DestinationFolderName of thisfolder with replacing
    end tell
end repeat
end adding folder items to

我现在的困境是如何更改 set DestinationFolderName to "A" 以响应 this_item 的文件名。

我尝试了set DestinationFolderName to text 1 thru 1 of filename 和其他一些迭代,但问题似乎在于找到文件名以提取第一个字母。

任何帮助将不胜感激。

【问题讨论】:

    标签: applescript subdirectory


    【解决方案1】:

    首先,不鼓励您将文件移动到文件夹操作文件夹的子文件夹中,因为在您创建子文件夹时,文件夹操作会再次触发,这可能会导致无限循环。

    要将文件移动到可能即时创建的文件夹,shell 命令ditto 是首选解决方案,因为它能够隐式创建中间目录。

    此代码使用桌面上的文件夹 Test 作为目标位置(尾部斜杠至关重要),并在 AppleScriptObjC 的帮助下使用处理程序来获取文件名的大写首字母。

    由于ditto 复制文件,因此需要额外的rm 行来删除源文件

    use AppleScript version "2.4" -- Yosemite (10.10) or later
    use scripting additions
    
    use framework "Foundation"
    
    on adding folder items to thisfolder after receiving added_items
        set destinationFolder to POSIX path of (path to desktop) & "Test/"
        repeat with i from 1 to number of items in added_items
            set this_item to item i of added_items
            tell application "System Events" to set fileName to name of this_item
            set prefix to uppercasedFirstCharacter(fileName)
            set destinationFile to destinationFolder & prefix & "/" & fileName
            do shell script "ditto " & quoted form of POSIX path of this_item & space & quoted form of destinationFile
            do shell script "rm " & quoted form of POSIX path of this_item
        end repeat
    end adding folder items to
    
    
    on uppercasedFirstCharacter(theString)
        set cocoaString to current application's NSString's stringWithString:theString
        return (cocoaString's substringToIndex:1)'s uppercaseString() as text
    end uppercasedFirstCharacter
    

    【讨论】:

    • 太好了,没想到循环效果!已经尝试过您的代码并且对文件很有用,但唯一的问题是它无限地重复新的字母文件夹作为子文件夹 - 任何想法如何修改?感谢您的回复!
    • 文件夹的行为应该如何?该脚本为每个(第一个)字母创建一个子文件夹,并相应地分发文件和文件夹。如果涉及文件夹,您必须进行的唯一更改是编写 "rm -r " 以递归删除文件夹。
    • 啊,似乎如果没有创建文件夹,那么它将继续复制它们 - 但提供 A-Z 文件夹已经使其完美运行。非常感谢
    【解决方案2】:

    正如@vadian 提供的答案中所述,将文件移动到带有附加文件夹操作命令的文件夹的子文件夹中绝不是一个好主意。

    出于此脚本的目的,我在桌面上创建了一个名为“New Destination”的新(移动到)文件夹,其中将包含子文件夹“A”、“B”、“C”等……

    如果正在移动的文件,例如以字母“D”开头,并且没有相应的移动到名为“D”的目标文件夹,则在名为“New Destination”的文件夹内,将自动创建文件夹“D”

    SATIMAGE Scripting Addition在此脚本中使用,如果被移动文件名的第一个字母是小写,则可能创建的相应文件夹将由小写变为大写

    property DestinationFolderName : missing value
    property moveToFolder : (path to desktop folder as text) & "New Destination"
    
    on adding folder items to this_folder after receiving these_items
        repeat with i from 1 to number of items in these_items
            set this_item to item i of these_items
            tell application "Finder"
                set fileName to name of item this_item
                set DestinationFolderName to character 1 of fileName
            end tell
    
            -- SATIMAGE scripting addition is needed for next command
            set DestinationFolderName to uppercase DestinationFolderName
    
            tell application "Finder"
                set checkExists to moveToFolder & ":" & DestinationFolderName
                try
                    if not (exists of checkExists) then
                        make new folder at moveToFolder ¬
                            with properties {name:DestinationFolderName}
                    end if
                end try
                move this_item to folder DestinationFolderName of folder moveToFolder with replacing
            end tell
        end repeat
    end adding folder items to
    

    【讨论】:

      【解决方案3】:

      我可以看到您已经在这方面获得了帮助,但我想提供另一种替代解决方案,它不使用外部框架或第三方工具(当然,并不是说使用这些有什么问题)。

      我还想评论一下使用监视文件夹作为您创建更多子文件夹的根目录的问题,我将在展示我的脚本后进行:

          property alphabet : "ABCDEFGHIJKLMNOPQRSTUVWXYZ:abcdefghijklmnopqrstuvwxyz"
      
      
          on adding folder items to thisfolder after receiving added_items
              
              tell application "Finder" to ¬
                  repeat with this_item in the added_items
                      get this_item's name
                      get the first character of the result
                      my capitalise(the result)
      
                      set DestinationFolderName to the result
                      
                      if not (exists folder DestinationFolderName in folder thisfolder) then ¬
                          make new folder in folder thisfolder with properties ¬
                              {name:DestinationFolderName}
                      
                      move this_item to folder DestinationFolderName of folder thisfolder
                  end repeat
              
          end adding folder items to
      
      
          to capitalise(l as text)
              local l
              
              considering case
                  set x to (the offset of l in the alphabet) mod 27
              end considering
              
              return character x of the alphabet
          end capitalise
      

      您会注意到该脚本包含一个我编写的子例程(处理程序),名为capitalise()。这需要一个字母并以大写形式返回它,基本上只使用一行代码。

      检索添加的项目的名称,其首字母大写。如果使用该字母命名的子文件夹尚不存在,则创建一个,然后将添加的项目移入其中。

      它与您的脚本基本相同,只是增加了使用文件名的第一个字母即时创建文件夹的功能。


      关于无限回归...

      关于在监视文件夹中创建子文件夹导致无限循环的恐惧,@vadian 强调这个问题是绝对正确的,因为它可能会以他描述的方式表现出来。在编写涉及更改被监视文件夹的脚本时需要注意这一点,通常最简单的做法是避免这样做。

      但是,在某些情况下,您可能想要需要将文件存储在被监视的文件夹中。如果您从未被允许这样做,那么被监视的文件夹就不会真正发挥其作为文件夹的作用;它只是充当 droplet(您将文件和文件夹拖放到其上以对其执行一些操作的脚本)。

      因此,虽然您绝对应该小心以这种方式使用受监视的文件夹,但您可以通过适当的保护措施来非常合理地这样做,以防止无限倒退。举个简单的例子,假设您的脚本只需要对文件 文件夹进行排序;简单的解决方案是让脚本忽略它收到的任何文件夹。

      但实际上,我们甚至不需要在这里这样做:我们可以让它平等地处理文件和文件夹,不会发生任何不愉快的事情。

      这是创建子文件夹然后将项目移入其中的脚本部分:

          if not (exists folder DestinationFolderName in folder thisfolder) then ¬
              make new folder in folder thisfolder with properties ¬
                          {name:DestinationFolderName}
      
          move this_item to folder DestinationFolderName of folder thisfolder
      

      注意子文件夹总是创建在同一个地方:thisfolder,也就是被监视的文件夹;它不是试图创建嵌套文件夹。也不是这样,如果已经存在一个使用正在处理的字母命名的文件夹,那么它不会尝试创建另一个。最后一个潜在的担忧可能来自尝试将move 子文件夹放入其自身。嗯,这不能在 Finder 中完成。这是不可能。所以,脚本会默默地抛出错误,然后终止,这正是我们想要的。

      总结

      我并不是在强迫您选择一种方法而不是另一种方法,也不是无视熟练程序员(例如 @vadian)的重要建议。

      但是,您可以使用您的监视文件夹将已排序的文件非常安全地存储在其子文件夹中,提供您注意如何编写这些内容。

      【讨论】:

      • 这真的很有帮助,总是很容易理解 /why/ 做事,而不是仅仅一个有效的解决方案!最大的优势是我可以将脚本附加到服务器上的文件夹,这是我的最终游戏!感谢@vadian、CJK、wch1zpink 的所有帮助
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-11-08
      • 2014-08-15
      • 1970-01-01
      • 2013-12-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多