Applescript:使用新URL编辑bookmark.plist文件

时间:2018-03-05 02:43:56

标签: applescript plist

set some_host to "test.mydomain.com"

try
    -- Ping the host.
    do shell script "ping -c 1 -t 1 " & some_host
    -- Set ipAddr.
    set ipAddr to word 3 of result
    -- Combine the IP with the URL & port.
    set urlAddr to "http://" & ipAddr & ":80"
    display dialog "Connection Successful. " & urlAddr buttons {"OK"} default button 1
on error
    -- if we get here, the ping failed
    display dialog "Conection failed. " & some_host & " is down" buttons {"OK"} default button 1
    return
end try

-- Update the URL with the new IP.
tell application "System Events"
    tell property list file "~/Library/Safari/Bookmarks.plist"
    set value of property list item "key" to text of urlAddr
    end tell
end tell

这是我得到的错误。我应该提到“密钥”将替换为我试图更改的书签名称。

error "System Events got an error: Can’t set property list item \"key\" of property list file \"~/Library/Safari/Bookmarks.plist\" to \"http://000.000.000.000:80\"." number -10006 from property list item "key" of property list file "~/Library/Safari/Bookmarks.plist"

Bookmark.plist示例:所以我们将“Key”替换为“NVR Camera”

<dict>
        <key>URIDictionary</key>
        <dict>
            <key>title</key>
            <string>NVR Camera</string>
        </dict>
        <key>URLString</key>
        <string>https://12.123.456.789:88</string>
        <key>WebBookmarkType</key>
        <string>WebBookmarkTypeLeaf</string>
        <key>previewText</key>
        <string>your description</string>
        <key>previewTextIsUserDefined</key>
        <true/>
    </dict>

我正在尝试这样做,以便在更改时自动将URL更新为新IP。如果有人有更好的解决方案,我全都耳朵!提前谢谢!

1 个答案:

答案 0 :(得分:1)

财产清单数据与XML数据

这是 Safari bookmarks.plist 文件的摘录:

    <?xml version=\"1.0\" encoding=\"UTF-8\"?>
    <!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">
    <plist version=\"1.0\">
    <dict>
        <key>Children</key>
        <array>
            <dict>
                <key>Title</key>
                <string>History</string>
                <key>WebBookmarkIdentifier</key>
                <string>History</string>
                <key>WebBookmarkType</key>
                <string>WebBookmarkTypeProxy</string>
                <key>WebBookmarkUUID</key>
                <string>92E8B75A-B335-4CA3-8DE9-08A09817792D</string>
            </dict>
            <dict>
                <key>Children</key>
                <array>
                    <dict>
                        <key>ReadingListNonSync</key>
                        <dict>
                            <key>neverFetchMetadata</key>
                            <false/>

这只是前24行,其中标签为<key>的标签已经出现了8次 - 大约每三行一次。您可以想象为什么AppleScript在被告知要获取名为"key"的标签时会有点困惑。

话虽如此,这并不是你的脚本抛出错误的原因。我在脚本编辑器中运行了此命令:

    tell application "System Events" to ¬
        tell the property list file ¬
            "~/Library/Safari/Bookmarks.copy.plist" to ¬
            get every property list item whose name is "key"

(我正在使用bookmarks.plist文件的副本,因为AppleScript的功能并不完全搞砸了它读取或写入的任何.plist文件。)

该命令的输出为:{},告诉我们没有标记为key的属性列表项。

虽然plist文件看起来像XML,但AppleScript处理数据的方式与XML文件的方式不同。使用XML文件,您可以使用其标记的名称来引用元素,例如<key>。使用属性列表文件,元素在键/值对中引用,因此,当XML数据中的<key>标记具有由名称"key"表示的时,对于一个plist,它将包含属性的 name ,其值将紧随其后。

例如:

    <key>Title</key>
    <string>History</string>

使用AppleScript中的XML数据,我们有两个XML元素:一个名为"key",值为"Title";另一个名为"string",值为"History"。使用plist数据,我们只有一个属性列表键/值对(item),其名称为"Title",其值为"History"

回到我的初始点,确实有多个同名的标签;同样,具有相同键的多个键/值对,并且很可能是相同的值。

因此,无论您将数据作为XML还是作为属性列表处理,都必须总是告诉AppleScript您引用的属性列表树的级别。

AppleScripting

要引用的层次结构的级别完全取决于您要存储书签的位置:在其自己的文件夹中;在收藏夹文件夹或已存在的其他文件夹中;或者只是在书签集合的顶层,以便在打开书签侧栏时它立即显示在列表中。

为方便起见,我将演示最后一个选项:将书签添加到文件夹树的顶层。我在下面的plist文件中标记了要插入的新条目:

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
    <plist version="1.0">
    <dict>
        <key>Children</key>
        <array>
            <dict>...</dict>
            <dict>...</dict>
            <dict>...</dict>
            <!-- etc... //-->
            <dict>...</dict>
            <!-- insert new entry here //-->
        </array>
        <!-- other stuff //-->
    </dict>
    </plist>

如果您运行此命令:

    tell application "System Events" to ¬
        tell the property list file ¬
            "~/Library/Safari/Bookmarks.copy.plist" to ¬
            get the properties of the last property list item of ¬
                the property list item "Children"

AppleScript将返回记录,这是(较少)尝试将数据存储为键/值对。它基本上是AppleScript列表,其中列表中的每个条目都有一个标签,用于引用项目而不是索引号。输出返回如下所示(为便于阅读而格式化):

     {value:{URIDictionary: ¬
         {title:"website.com"}, ¬
          previewText:"The title of the website", ¬
          ReadingListNonSync:{neverFetchMetadata:false}, ¬
          Sync:{ServerID:"DAV-DB576E16-E590-44D3-839F-63C0A1A8D3BC", ¬
               |data|:«a whole lot of data»}, ¬
          WebBookmarkUUID:"A5E4774A-2C26-4AD1-9938-D192C26860B8", ¬
          URLString:"https://website.com/path/etc", ¬
          WebBookmarkType:"WebBookmarkTypeLeaf", ¬
          previewTextIsUserDefined:true}, ¬
      kind:record, ¬
      class:property list item, ¬
      name:missing value, ¬
      text:"The XML representation of the property list data."}

这告诉我哪些项构成了plist文件中的单个书签条目。请记住,从AppleScript的角度来看,每个项目本身都是property list item,因此需要单独创建。我假设我们可以忽略WebBookmarkUUIDsync,它们都包含我们自己无法生成的数据。但其余的都很简单。

创建新的书签条目

    set urlAddr to "http://000.000.000.000:80"

    tell application "System Events" to tell ¬
        the property list file "~/Library/Safari/Bookmarks.plist" to tell ¬
        the property list item "Children" to tell ¬
        (make new property list item ¬
            at end of property list items ¬
            with properties {kind:record})

        make new property list item with properties ¬
            {name:"URIDictionary", kind:record}

        tell the result to make new property list item ¬
            with properties {name:"title", value:"mydomain.com", kind:string}

        make new property list item with properties ¬
            {name:"previewText", value:"Information about mydomain.com", kind:string}

        make new property list item with properties ¬
            {name:"URLString", value:urlAddr, kind:string}

        make new property list item with properties ¬
            {name:"WebBookmarkType", value:"WebBookmarkTypeLeaf", kind:string}

        make new property list item with properties ¬
            {name:"previewTextIsUserDefined", value:true, kind:boolean}

        make new property list item with properties ¬
            {name:"_tag", value:"AppleScript", kind:string}
    end tell

    return the result

在我的系统上运行此功能,成功创建了一个名为&#34; mydomain.com&#34;的新书签条目,点击后,尝试将我带到URL&#34; http://000.000.000.000&#34 ; (根据urlAddr变量的虚拟值。

更新书签

要在每次运行脚本时更新它,您所要做的就是获取对书签的引用,然后引用property list item,其中包含有关书签指向的URL的信息。

您会注意到,在上面,我创建了一个名为_tag的属性列表项,其他书签条目没有。我做了这个,所以只需搜索包含_tag的那个就可以轻松获得书签的引用:

    tell application "System Events" to tell ¬
        the property list file "~/Library/Safari/Bookmarks.copy.plist" to tell ¬
        the property list item "Children" to ¬
        set bookmark to ¬
            the first property list item whose ¬
            name of property list items contains "_tag"

将书签引用存储在变量bookmark中,更新它指向的URL就像这样:

    tell application "System Events" to tell ¬
        the property list file "~/Library/Safari/Bookmarks.plist" to tell ¬
        the property list item "Children"

        set bookmark to ¬
            the first property list item whose ¬
            name of property list items contains "_tag"

        set URLString to the first property list item ¬
            of bookmark whose name is "URLString"

        set the value of URLString to urlAddr
    end tell

UPDATE:

在进一步测试并返回以检查通过AppleScript提交的更改后的bookmarks.plist文件时,会出现 Safari 自动删除用户定义键_tag,这是一种耻辱。相反,它会插入WebBookmarkUUID并为其生成值,这很棒。

所以,遗憾的是,我们无法使用上述方法来标记我们的书签条目,以便以后轻松引用。

因此,这个新脚本必须更长。它旨在替换以tell application "System Events"开头的脚本部分。

首先检查书签层次结构的顶层是否存在与指定的title匹配的书签;如果没有,它会创造它;如果是,它将使用变量urlAddr中包含的内容更新它指向的地址。

    set urlAddr to "http://google.com"
    set myTitle to "mydomain.com"
    set plistFile to "~/Library/Safari/Bookmarks.plist"


    tell application "System Events"
        tell ¬
            the property list file plistFile to tell ¬
            the property list item "Children" to ¬
            set top_level to a reference to it


        set bookmarks to a reference to ¬
            (property list items of the top_level ¬
                whose name of property list items ¬
                contains "URLString")

        set labels to ¬
            a reference to property list item "title" of ¬
                property list item "URIDictionary" of ¬
                property list items of ¬
                the bookmarks


        if the value of the result ¬
            does not contain myTitle then ¬
            return saveBookmark of me ¬
                for urlAddr ¬
                to plistFile ¬
                at a reference to property list items of the top_level ¬
                given |title|:myTitle, previewText:"your description"


        repeat with i from the number of bookmarks to 1 by -1

            if item i of ¬
                the value of the labels is ¬
                myTitle then ¬
                exit repeat

        end repeat

        set bookmark to item i of bookmarks
        set the value of ¬
            property list item "URLString" of ¬
            the bookmark to ¬
            the urlAddr
    end tell


    to saveBookmark for www as string ¬
        at locationRef ¬
        to plist as string : "~/Library/Safari/Bookmarks.plist" given title:T ¬
        as string, previewText:_t as string : ""

        local www, locationRef, plist
        local T, _t


        tell application "System Events" to tell the property list file plist

            tell (make new property list item at end of locationRef ¬
                with properties {kind:record})

                tell (make new property list item with properties ¬
                    {name:"URIDictionary", kind:record}) to ¬
                    make new property list item with properties ¬
                        {name:"title", value:T, kind:string}

                make new property list item with properties ¬
                    {name:"previewText", value:_t}

                make new property list item with properties ¬
                    {name:"URLString", value:www}

                make new property list item with properties ¬
                    {name:"WebBookmarkType", value:"WebBookmarkTypeLeaf"}

                make new property list item with properties ¬
                    {name:"previewTextIsUserDefined", value:true}

            end tell
        end tell
    end saveBookmark

如果您的书签存在于书签层次结构的其他位置(例如文件夹中),则目前无法找到它,并且将在顶层创建新书签。我将让您使用我在此示例脚本中演示的内容,并可能对书签文件夹树进行更深入的遍历。

如果您有任何问题或疑问,请发表评论,我会尽快回复您。

相关问题