确定文件是否在任何macOS废纸folder文件夹中

问题描述

有一个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;
}

解决方法

意识到[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/"]
                                )
                  );

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...