NSFileManager删除目录内容

36

如何在不删除目录本身的情况下删除目录中的所有内容?我想基本上清空一个文件夹,但保留它(和权限)。

9个回答

84
例如,通过使用目录枚举器:
NSFileManager *fileManager = [[NSFileManager alloc] init];
NSDirectoryEnumerator *enumerator = [fileManager enumeratorAtPath:path];    
NSString *file;

while (file = [enumerator nextObject]) {
    NSError *error = nil;
    BOOL result = [fileManager removeItemAtPath:[path stringByAppendingPathComponent:file] error:&error];

    if (!result && error) {
        NSLog(@"Error: %@", error);
    }
}

Swift

let fileManager = NSFileManager.defaultManager()
let enumerator = fileManager.enumeratorAtURL(cacheURL, includingPropertiesForKeys: nil, options: nil, errorHandler: nil)

while let file = enumerator?.nextObject() as? String {
    fileManager.removeItemAtURL(cacheURL.URLByAppendingPathComponent(file), error: nil)
}

2
不要忘记在尝试使用错误对象之前检查removeItemAtPath:是否实际失败。至少,您可能会报告比实际更多的错误。 - Peter Hosey
你的 while 循环有问题,你不能在 while 括号内声明变量!! - Psycho
3
@Psycho:这对于Objective-C是真的,但对于Objective-C++也可以正常工作。当这与问题无关且易于修复时,值得进行反对吗?我认为不需要... - Georg Fritzsche
下降票是针对解决方案的,只需通过保存权限而不是迭代内容来删除整个目录。 - Psycho

11

试一下这个:

NSFileManager *manager = [NSFileManager defaultManager];
NSString *dirToEmpty = ... //directory to empty
NSError *error = nil;
NSArray *files = [manager contentsOfDirectoryAtPath:dirToEmpty 
                                              error:&error];

if(error) {
  //deal with error and bail.
}

for(NSString *file in files) {
    [manager removeItemAtPath:[dirToEmpty stringByAppendingPathComponent:file]
                        error:&error];
    if(error) {
       //an error occurred...
    }
}    

contentsOfDirectoryAtPath:: 方法无法提供内容的完整路径。 - Georg Fritzsche
不需要测试“.”或“..”,因为contentsOfDirectoryAtPath:error会将它们_过滤掉_。来自文档的描述:搜索是浅层的,因此不会返回任何子目录的内容。返回的数组不包含当前目录(“。”)、父目录(“..”)或资源叉(以“._”开头),也不遍历符号链接。 - petert
@petert 哇,这是一个非常古老的答案。感谢提供信息。 - Jacob Relkin

5

在Swift 2.0中:

if let enumerator = NSFileManager.defaultManager().enumeratorAtPath(dataPath) {
  while let fileName = enumerator.nextObject() as? String {
    do {
        try NSFileManager.defaultManager().removeItemAtPath("\(dataPath)\(fileName)")
    }
    catch let e as NSError {
      print(e)
    }
    catch {
      print("error")
    }
  }
}

4

如果有人需要快速复制/粘贴,这里提供了Swift 3版本。

let fileManager = FileManager.default
let fileUrls = fileManager.enumerator(at: folderUrl, includingPropertiesForKeys: nil)
while let fileUrl = fileUrls?.nextObject() {
    do {
        try fileManager.removeItem(at: fileUrl as! URL)
    } catch {
        print(error)
    }
}

3

Swift 2.1.1:

public func deleteContentsOfFolder()
{
    // folderURL
    if let folderURL = self.URL()
    {
        // enumerator
        if let enumerator = NSFileManager.defaultManager().enumeratorAtURL(folderURL, includingPropertiesForKeys: nil, options: [], errorHandler: nil)
        {
            // item
            while let item = enumerator.nextObject()
            {
                // itemURL
                if let itemURL = item as? NSURL
                {
                    do
                    {
                        try NSFileManager.defaultManager().removeItemAtURL(itemURL)
                    }
                    catch let error as NSError
                    {
                        print("JBSFile Exception: Could not delete item within folder.  \(error)")
                    }
                    catch
                    {
                        print("JBSFile Exception: Could not delete item within folder.")
                    }
                }
            }
        }
    }
}

2

contentsOfDirectoryAtPath:error: 的文档说明如下:

搜索是浅层的,因此不返回任何子目录的内容。该返回数组不包含当前目录(“.”)、父目录(“..”)或资源叉(以“._”开头),也不遍历符号链接。

因此:

---( file != @"." && file != @".." )---

与 IT 技术无关。


2
你可以像这样扩展 NSFileManager
extension NSFileManager {
  func clearFolderAtPath(path: String) -> Void {
      for file in subpathsOfDirectoryAtPath(path, error: nil) as? [String] ?? []  {
          self.removeItemAtPath(path.stringByAppendingPathComponent(file), error: nil)
      }
  }
}

接下来,您可以像这样清除文件夹:NSFileManager.defaultManager().clearFolderAtPath("文件夹路径")


1
Georg Fritzsche的Swift解决方案对我无效。不要将枚举对象读取为字符串,而应该将其读取为NSURL。
let fileManager = NSFileManager.defaultManager()
let url = NSURL(string: "foo/bar")
let enumerator = fileManager.enumeratorAtURL(url, includingPropertiesForKeys: nil, options: nil, errorHandler: nil)
while let file = enumerator?.nextObject() as? NSURL {
    fileManager.removeItemAtURL(file, error: nil)
}

0
为什么不删除整个目录,然后重新创建呢?只需在删除之前获取文件属性和权限,然后使用相同的属性重新创建即可。

1
为什么要删除文件夹并可能遇到问题(例如权限),如果可以只删除其中的内容呢? - Georg Fritzsche
1
通常最好的做法是扫描目录并从源代码中删除文件,因为这样更可靠,可以更好地恢复和报告错误。 - petert

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接