【问题标题】:Check if directory is empty or remove only if empty in Objective-C检查目录是否为空或仅在 Objective-C 中为空时删除
【发布时间】:2012-07-04 14:55:58
【问题描述】:

NSFileManager removeItemAtURL 只执行递归删除。对非空目录没有特殊处理。

如何通过事先测试条件仅删除空目录?有contentsOfDirectoryAtPath 可以获取文件列表,可能是空的,不过这样就大材小用了。

或者,是否有一个功能可以仅在为空时将其删除,例如好的 ol'rmdir?啊,我可以这样称呼……

【问题讨论】:

    标签: objective-c nsurl nsfilemanager


    【解决方案1】:

    这不是矫枉过正......如果你想要一个类似- isEmptyDirectoryAtURL: 的方法,那就去做吧:

    @interface NSFileManager (EmptyDirectoryAtURL)
    - (BOOL)isEmptyDirectoryAtURL:(NSURL*)url;
    @end
    
    @implementation NSFileManager (EmptyDirectoryAtURL)
    
    - (BOOL)isEmptyDirectoryAtURL:(NSURL*)url
    {
      // This assumes you know the URL you have is actually a
      // directory and should be enhanced to ensure that
      return ([[self contentsOfDirectoryAtURL:url includingPropertiesForKeys:nil options:0 error:NULL] count] <= 1);
    }
    
    @end
    

    【讨论】:

    • @Potatoswatter 如果 URL 不存在,它将返回 0,但如果 URL 存在且为空,则魔术自引用将成为返回内容的一部分(@987654323 @ 目录),因此如果它在那里并且为空,它实际上将始终为 1。你可以传递一个选项来排除隐藏文件,其中包括.,但你的目录实际上并不是空的,所以最好不要这样做。
    • 在实践中,我没有看到'.'从 contentsOfDirectory 返回的数组中返回的目录。虽然有一个通常会返回的文件是可删除的,但它是由 Spotlight 创建的“.DS_Store”。但是,使用
    【解决方案2】:

    如果你想留在基金会的土地上,你必须使用它,没有其他办法。

    但是如果你这样做,你会引入一个竞争条件:在你列出目录的内容之后,在你删除它之前,一些其他程序可能会在那里写入一个新文件,然后该文件会被删除。因此,您必须接受要删除文件夹及其所有内容的事实,或者您必须寻找不同的 API。

    您可以使用 POSIX rmdir 函数来实现您的目标,如下所示:

    NSString *path = [url path];
    int result = rmdir( [path fileSystemRepresentation] );
    if (result == 0) // everything ok
    else // lookup error code from errno
    

    如果目录不为空,则会收到错误代码ENOTEMPTY

    【讨论】:

    • 嘿,我刚刚编辑了问题,在您提交答案的一秒钟内提到了rmdir。这可能是最好的方式,即使我在 iPhone 上。 +1
    • 即使我提出了其他建议,我也为此 +1。仅仅因为您使用的是 iPhone 并不意味着使用 POSIX 库调用有什么问题 - 我自己更喜欢使用它们而不是 Foundation
    • @JasonCoco POSIX 很棒,但这是我第一次在 Foundation 中工作,所以我比以前更坚持它,只是为了教育。但 iPhone 确实意味着不会有文件系统竞争条件。
    • @Potatoswatter 是的,除非您在无处不在的容器空间中胡闹:)在这种情况下,竞争条件可以返回!
    【解决方案3】:

    为什么不实现 NSFileManager 委托方法 "fileManager:shouldRemoveItemAtURL:" 并在该委托方法实现中快速检查 A) 项目是否为目录 B) 在返回“YES”之前该目录是否为空。

    【讨论】:

    • 这根本不是一个答案,也不是一个好的建议。我应该在一个地方用一个全局委托方法替换一个特定的if 语句,可能在另一个文件中关闭,以仲裁删除所有内容?
    • 是的,这是一个很好的答案和一个很好的建议。在“remoteItemAtURL”时间,NSFileManager 进行删除之前调用该委托方法,以确定是否可以删除该内容。在您的情况下,您只想删除通过特定条件的内容。例如。空目录。对于我自己的代码,我宁愿依赖 Cocoa 框架提供的东西,但听起来你更喜欢直接的 C / UNIX / POSIX 东西。所以 +1 斯文的优秀答案。
    • 我问如何检查目录是否为空。您的建议是创建一个接受 URL 并检查它是否为空目录的新函数。没有答案。
    • 另外,您可以通过 alloc/init 针对这种特定情况创建自己的 NSFileManager。您不需要将委托连接到单例。我想知道当您在目录上调用removeItemAtURL: 时,是否会首先调用fileManager:shouldRemoveItemAtURL: 来获取其内容。如果是这种情况,如果您发现它试图删除文件而不是您的目录,您可以中止。
    • 我会在这里留下我的答案,即使它会收集反对票,因为你的问题不清楚(你问如何只删除空目录)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-17
    • 1970-01-01
    • 1970-01-01
    • 2018-12-23
    • 1970-01-01
    • 2017-03-05
    相关资源
    最近更新 更多