<p>使用PyObjC解决了这个问题,尽管几乎没有关于PyObjC的文档。您必须小心地将NSURL调用的ObjectiveC接口转换为PyObjC,使用在<a href="https://pythonhosted.org/pyobjc/" rel="nofollow noreferrer">this site</a>上找到的“PyObjC简介”中描述的技术,同时引用<a href="https://developer.apple.com/documentation/foundation/nsurl?language=objc" rel="nofollow noreferrer">here</a>中描述的NSURL接口。在</p>
<p>@MagerValp对<a href="https://stackoverflow.com/questions/21244781">this question</a>的回复中的代码有助于找出如何获取别名的目标。我不得不想出如何用修改后的目标创建一个新别名。在</p>
<p>下面是一个测试程序,它包含并练习了所需的所有功能。它的设置和使用在代码中用注释记录下来。在</p>
<p>我是个坏人,不做doc字符串或者输入和返回值的描述,但是我保持了所有函数的简短和单一函数,希望我已经足够清楚地命名了所有变量和函数,使它们不再需要。有一个公认的奇怪的组合,CamelCaps和下划线_分开的变量和函数名。我通常对全局常量使用CamelCaps,对函数和变量使用下划线分隔的名称,但在本例中,我希望保持PyObjC调用中引用的变量和数据类型不变,这是一种奇怪的混合。在</p>
<p>警告一下,macfinder会缓存一些关于别名的信息。因此,如果您在运行这个程序之后立即对<code>file_alias</code>执行Get Info或解析,那么它看起来好像不起作用,尽管它确实起了作用。您必须将<code>one</code>文件夹拖到Trash<strong>并清空垃圾桶,只有这样,<code>file_alias</code>的Get Info或解析才会显示它现在确实指向<code>./two/file.txt</code>。幸运的是,这不会影响我使用这些技术,也不会影响大多数人的使用,我怀疑。程序的重点通常是用一个固定的别名替换一个损坏的别名,这是基于这样一个事实:一些简单的事情发生了变化,比如本例中的文件夹名,或者我的实际应用程序中的卷名。在</p>
<p>最后,代码:</p>
<pre><code>#!/usr/bin/env python
# fix_alias.py
# A test program to exercise functionality for retargeting a macOS file alias (bookmark).
# Author: Larry Yaeger, 20 Feb 2018
#
# Create a file and directory hierarchy like the following:
#
# one
# file.txt
# two
# file.txt
# file_alias
#
# where one and two are folders, the file.txt files are any files really, and
# file_alias is a Mac file alias that points to ./one/file.txt. Then run this program
# in the same folder as one, two, and file_alias. It will replace file_alias with
# an alias that points to ./two/file.txt.
#
# Note that file_alias is NOT a symbolic link, even though the Mac Finder sometimes
# pretends symbolic links are aliases; they are not.
import os
import string
from Foundation import *
OldFolder = 'one'
NewFolder = 'two'
AliasPath = 'file_alias'
def get_bookmarkData(alias_path):
alias_url = NSURL.fileURLWithPath_(alias_path)
bookmarkData, error = NSURL.bookmarkDataWithContentsOfURL_error_(alias_url, None)
return bookmarkData
def get_target_of_bookmarkData(bookmarkData):
if bookmarkData is None:
return None
options = NSURLBookmarkResolutionWithoutUI | NSURLBookmarkResolutionWithoutMounting
resolved_url, stale, error = \
NSURL.URLByResolvingBookmarkData_options_relativeToURL_bookmarkDataIsStale_error_(
bookmarkData, options, None, None, None)
return resolved_url.path()
def create_bookmarkData(new_path):
new_url = NSURL.fileURLWithPath_(new_path)
options = NSURLBookmarkCreationSuitableForBookmarkFile
new_bookmarkData, error = \
new_url.bookmarkDataWithOptions_includingResourceValuesForKeys_relativeToURL_error_(
options, None, None, None)
return new_bookmarkData
def create_alias(bookmarkData, alias_path):
alias_url = NSURL.fileURLWithPath_(alias_path)
options = NSURLBookmarkCreationSuitableForBookmarkFile
success, error = NSURL.writeBookmarkData_toURL_options_error_(bookmarkData, alias_url, options, None)
return success
def main():
old_bookmarkData = get_bookmarkData(AliasPath)
old_path = get_target_of_bookmarkData(old_bookmarkData)
print old_path
new_path = string.replace(old_path, OldFolder, NewFolder, 1)
new_bookmarkData = create_bookmarkData(new_path)
new_path = get_target_of_bookmarkData(new_bookmarkData)
print new_path
os.remove(AliasPath)
create_alias(new_bookmarkData, AliasPath)
main()
</code></pre>