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

Applescript:使用新URL编辑bookmark.plist文件,applescript,plist,Applescript,Plist,这是我得到的错误。我应该提到,“key”将被替换为我试图更改的书签名称 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 & p

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

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
Bookmark.plist示例:让我们用“NVR摄像头”替换“键”


乌里韦字典
标题
NVR摄像机
URL字符串
https://12.123.456.789:88
WebBookmarkType
WebBookmarkTypeLeaf
预览文本
你的描述
previewTextIsUserDefined
我正在尝试这样做,以便在URL发生更改时自动将其更新为新的IP。如果有人有更好的解决办法,我洗耳恭听!提前谢谢

属性列表数据与XML数据 以下是我的Safaribookmarks.plist文件的摘录:

<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>
(我使用的是bookmarks.plist文件的副本,因为它不会完全破坏AppleScript读取或写入的任何.plist文件。)

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

尽管plist文件看起来像XML,但AppleScript处理数据的方式与XML文件不同。对于XML文件,可以使用其标记的名称引用元素,例如
。对于属性列表文件,元素以键/值对引用,因此,如果XML数据中的
标记将有一个值,该值由名称
“key”
表示,对于plist,它将包含紧跟其后的属性的名称

例如:

    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"
如果运行此命令:

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

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

创建新的书签条目 在我的系统上运行此操作成功创建了一个名为“mydomain.com”的新书签条目,单击该条目时,它试图将我带到URL“”(根据
urlAddr
变量的伪值)

更新书签 要在每次运行脚本时更新它,只需获取对书签的引用,然后获取对
属性列表项的引用,该属性列表项包含有关书签指向的URL的信息

您会注意到,在上面,我创建了一个名为
\u-tag
的属性列表项,而其他书签条目没有该项。我这样做是为了通过搜索包含
\u-tag
的属性列表项,轻松获取对书签的引用:

    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
使用存储在变量
bookmark
中的书签引用,更新其指向的URL的操作如下:

    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"
更新: 在通过AppleScript提交更改后,进一步测试并检查
bookmarks.plist
文件后,Safari会自动删除用户定义的键
(标记
),这是一个遗憾。相反,它会插入
Webbookmarkuid
,并为其生成值我很好

因此,不幸的是,我们不能使用上面描述的方法标记书签条目,以便于以后参考

因此,这个新脚本需要更长的时间。它旨在替换脚本中以
告诉应用程序“系统事件”
开头的部分

它将首先检查与指定的
标题
匹配的书签是否存在于书签层次结构的顶层;如果不存在,它将创建书签;如果存在,它将使用变量
urlAddr
中包含的任何内容更新指向的地址

    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
如果您的书签存在于书签层次结构的其他位置(例如文件夹中),则当前将找不到它,并且将在顶层创建一个新书签。我将让您使用我在本示例脚本中演示的内容,并可能实现对书签文件夹树的更深入遍历

如果您有任何问题,请留言,我会回复您。

属性列表数据与XML数据 以下是我的Safaribookmarks.plist文件的摘录:

<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>
(我使用的是bookmarks.plist文件的副本,因为它不会完全破坏AppleScript读取或写入的任何.plist文件。)

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

尽管plist文件看起来像XML,但AppleScript处理数据的方式与XML文件不同。对于XML文件,您可以使用其标记的名称引用元素,例如
。对于属性列表文件,元素以键/值对引用,因此,XML数据中的
标记将具有由名称
“key”
表示,对于plist,它将包含紧跟其后的属性的名称

例如:

    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"
如果运行此命令:

    <?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>
AppleScript将返回一条记录,这是它(较少)将数据存储为键/值对的尝试。它基本上是一个AppleScript列表,其中列表中的每个条目都有一个标签,用于引用项而不是索引
    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"
    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
    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
touch UpdateIP; nano UpdateIP
chmod u+x UpdateIP
./UpdateIP
#!/bin/bash

set -e
# set -x

    # Host Name.

h="google.com"

    # Binary PLIST File.

bp="$HOME/Library/Safari/Bookmarks.plist"

    # XML File converted from Binary PLIST File.

bx="/tmp/Bookmarks.xml"

    # Get New Host IP Address.

nip="$(ping -c 1 -t 1 ${h} | grep -E -o -m 1 '[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+')"

    # Convert Binary PLIST File to XML File.

plutil -convert xml1 -o "${bx}" "${bp}"

    # Get Stored Host IP Address.

sip="$(grep -A3 -o 'NVR Camera' ${bx} | tail -1 | grep -E -o '[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+')"

    # Compare New Host IP Address against Stored Host IP Address.
    # If they do not match, then update the 'Bookmark.plist' file.

if [[ ! $nip == "$sip" ]]; then

    printf '  Host IP Address Did Not Match!\n  Updating Host IP Address...\n'

        # Backup Binary PLIST File.

    cp "${bp}" "${bp}$(date +.%m.%d.%Y_%H.%M.%S)"

        # Get line number containing the Host IP Address.

    ln="$(awk '/NVR Camera/{print NR+3; exit}' ${bx})"

        # Update Host IP Address in XML File.

    eval "sed -i -e ${ln}s#${sip}#${nip}# ${bx}"

        # Convert updated XML File to overwrite existing Binary PLIST File.

    plutil -convert binary1 -o "${bp}" "${bx}"

else

    printf '  Host IP Address Matched!\n'

fi
$ ./UpdateIP
+ h=google.com
+ bp=/Users/me/Library/Safari/Bookmarks.plist
+ bx=/tmp/Bookmarks.xml
++ ping -c 1 -t 1 google.com
++ grep -E -o -m 1 '[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+'
+ nip=172.217.4.46
+ plutil -convert xml1 -o /tmp/Bookmarks.xml /Users/me/Library/Safari/Bookmarks.plist
++ grep -A3 -o 'NVR Camera' /tmp/Bookmarks.xml
++ tail -1
++ grep -E -o '[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+'
+ sip=172.217.30.20
+ [[ ! 172.217.4.46 == \1\7\2\.\2\1\7\.\3\0\.\2\0 ]]
+ printf '  Host IP Address Did Not Match!\n  Updating Host IP Address...\n'
  Host IP Address Did Not Match!
  Updating Host IP Address...
++ date +.%m.%d.%Y_%H.%M.%S
+ cp /Users/me/Library/Safari/Bookmarks.plist /Users/me/Library/Safari/Bookmarks.plist.03.06.2018_16.50.00
++ awk '/NVR Camera/{print NR+3; exit}' /tmp/Bookmarks.xml
+ ln=98121
+ eval 'sed -i -e 98121s#172.217.30.20#172.217.4.46# /tmp/Bookmarks.xml'
++ sed -i -e 98121s#172.217.30.20#172.217.4.46# /tmp/Bookmarks.xml
+ plutil -convert binary1 -o /Users/me/Library/Safari/Bookmarks.plist /tmp/Bookmarks.xml
$ 
$ ./UpdateIP
+ h=google.com
+ bp=/Users/me/Library/Safari/Bookmarks.plist
+ bx=/tmp/Bookmarks.xml
++ ping -c 1 -t 1 google.com
++ grep -E -o -m 1 '[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+'
+ nip=172.217.4.46
+ plutil -convert xml1 -o /tmp/Bookmarks.xml /Users/me/Library/Safari/Bookmarks.plist
++ grep -A3 -o 'NVR Camera' /tmp/Bookmarks.xml
++ tail -1
++ grep -E -o '[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+'
+ sip=172.217.4.46
+ [[ ! 172.217.4.46 == \1\7\2\.\2\1\7\.\4\.\4\6 ]]
+ printf '  Host IP Address Matched!\n'
  Host IP Address Matched!
$ 
$ ./UpdateIP
  Host IP Address Did Not Match!
  Updating Host IP Address...
$ 
$ ./UpdateIP
  Host IP Address Matched!
$ 
$ ./UpdateIP
$