Applescript:如何根据文件名设置“移动到”文件夹,将文件排序为按字母顺序排列的文件夹?

时间:2018-02-27 16:49:06

标签: applescript subdirectory

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

我编写了以下代码,用于将添加到子文件夹“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和其他一些迭代,但问题似乎是找到提取第一个字母的文件名。

非常感谢任何帮助。

3 个答案:

答案 0 :(得分:1)

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

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

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

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

答案 1 :(得分:0)

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

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

如果要移动的文件,例如以字母“D”开头,并且没有相应的移动到名为“D”的目标文件夹,则在名为“新目的地”的文件夹中,将自动创建文件夹“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

答案 2 :(得分:0)

我已经看到你已经有了这方面的帮助,但我想提供另一种替代解决方案,它不使用外部框架或第三方工具(当然不是使用这些工具有任何问题)。

我还想评论使用监视文件夹作为创建更多子文件夹的根目录的问题,我将在演示脚本后执行此操作:

    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

可以,但是,使用你看过的文件夹可以非常安全地将已排序的文件存储在他们的子文件夹中,提供你要注意如何编写这些东西的脚本。