【问题标题】:Determine if a file is inside any macOS Trash folder确定文件是否在任何 macOS 废纸篓文件夹中
【发布时间】:2021-02-16 04:32:41
【问题描述】:

有一个similar question for iOS,但我发现建议的解决方案并非在所有情况下都适用于 macOS。

在 Mac 上,有许多可能的废纸篓文件夹:

  • /.Trashes
  • ~/.Trash
  • ~/Library/Mobile Documents/com~apple~CloudDocs/.Trash - 这个来自 iCloud
  • /Users/xxx/.Trash – 任何其他用户的垃圾
  • /Volumes/xxx/.Trashes

此代码应该可以工作,但不适用于 iCloud 垃圾箱:

NSURL *theURL = ...;
NSURLRelationship relationship = NSURLRelationshipOther;
NSError *error = nil;
[NSFileManager.defaultManager
         getRelationship: &relationship
             ofDirectory: NSTrashDirectory
                inDomain: 0
             toItemAtURL: theURL
                   error: &error];
BOOL insideTrash = !error && (relationship == NSURLRelationshipContains);

如果 URL 指向任何 iCloud 文件夹(包括上面显示的垃圾箱文件夹),我会收到以下错误:

Error Domain=NSCocoaErrorDomain Code=3328
"The requested operation couldn’t be completed because the feature is not supported."

奇怪的是,即使是 10.15 SDK 中“NSFileManager”的头文件也建议使用相同的代码:

/* trashItemAtURL:resultingItemURL:error: [...]

    To easily discover if an item is in the Trash, you may use
    [fileManager getRelationship:&result ofDirectory:NSTrashDirectory
       inDomain:0 toItemAtURL:url error:&error]
    && result == NSURLRelationshipContains.
 */

好像还有issue with trashItemAtURL: on iCloud-synched folders

那么,我该如何解决呢?如果 Finder 可以检测到 iCloud 垃圾,我也应该可以。

(注意:我用来测试的应用甚至没有沙盒)

更多发现:也因无效符号链接而失败

如果 url 指向目标不存在的符号链接,官方建议的使用 getRelationship: 的方法也会失败并出现错误。

所以,基本上,这个功能已经很糟糕了(在 10.13.6、10.15.7 和 11.0.1 中验证)。

这是演示该错误的代码,我已在 FB8890518 下向 Apple 提交了该代码:

#import <Foundation/Foundation.h>

static void testSymlink (NSString* symlinkName, NSString* symlinkTarget)
{
    NSString *path = [[NSString stringWithFormat:@"~/.Trash/%@", symlinkName] stringByExpandingTildeInPath];
    NSURL *url = [NSURL fileURLWithPath:path];
    symlink (symlinkTarget.UTF8String, path.UTF8String);
    NSLog(@"created symlink at <%@> pointing to <%@>", url.path, symlinkTarget);

    NSURLRelationship relationship = -1;
    NSError *error = nil;
    [NSFileManager.defaultManager getRelationship:&relationship ofDirectory:NSTrashDirectory inDomain:0 toItemAtURL:url error:&error];
    NSString *rel = @"undetermined";
    if (relationship == 0) rel = @"NSURLRelationshipContains";
    if (relationship == 1) rel = @"NSURLRelationshipSame";
    if (relationship == 2) rel = @"NSURLRelationshipOther";
    NSLog(@"result:\n relationship: %@\n error: %@", rel, error);
}

int main(int argc, const char * argv[])
{
    @autoreleasepool {
        testSymlink (@"validSymlink", @"/System");
        testSymlink (@"brokenSymlink", @"/nonexisting_file");
    }
    return 0;
}

【问题讨论】:

    标签: macos icloud icloud-documents


    【解决方案1】:

    意识到[NSFileManager getRelationship:] 甚至因符号链接损坏而失败,我得出结论,这是 macOS 中的一个错误,多年来一直未被发现。

    我想出了以下解决方法:

    使用getRelationship:操作,然后先检查返回的错误:

    • 如果没有错误,则检查relationship == NSURLRelationshipContains,并将其用作我的结果。
    • 否则,如果出现任何错误,请检查路径是否包含“/.Trash/”或“/.Trashes/” - 如果是,则假定该项目位于“回收站”文件夹中。
    NSURL *theURL = ...;
    NSURLRelationship relationship = NSURLRelationshipOther;
    NSError *error = nil;
    [NSFileManager.defaultManager
             getRelationship: &relationship
                 ofDirectory: NSTrashDirectory
                    inDomain: 0
                 toItemAtURL: theURL
                       error: &error];
    BOOL insideTrash =   !error && (relationship == NSURLRelationshipContains)
                       || error && (
                                        [theURL.path containsString:@"/.Trash/"]
                                     || [theURL.path containsString:@"/.Trashes/"]
                                    )
                      );
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-06
      • 2011-02-12
      • 1970-01-01
      • 2013-07-04
      相关资源
      最近更新 更多