47

Given a directory [[self documentsDirectory] stringByAppendingPathComponent:@"Photos/"] how do I delete ALL FILES in this folder?

(assume a correct documents directory path)

David Gelhar
  • 27,873
  • 3
  • 67
  • 84
RexOnRoids
  • 14,002
  • 33
  • 96
  • 136

5 Answers5

114
NSFileManager *fm = [NSFileManager defaultManager];
NSString *directory = [[self documentsDirectory] stringByAppendingPathComponent:@"Photos/"];
NSError *error = nil;
for (NSString *file in [fm contentsOfDirectoryAtPath:directory error:&error]) {
    BOOL success = [fm removeItemAtPath:[NSString stringWithFormat:@"%@%@", directory, file] error:&error];
    if (!success || error) {
        // it failed.
    }
}

I leave it up to you to do something useful with the error if it exists.

coneybeare
  • 33,113
  • 21
  • 131
  • 183
  • 20
    In general, you should probably use `stringByAppendingPathComponent` instead of `stringWithFormat` to concatenate paths. (I know the above works, but only because of your hard-coded trailing slash in `@"Photos/"`.) – zekel Sep 21 '11 at 21:01
  • Zekel is correct - it's important to use ```stringByAppendingPathComponent```, especially if you are, say, using it with iOS. – karlbecker_com Jun 26 '13 at 06:55
  • 2
    Actually the above code as it stands _does not_ work because `stringByAppendingPathComponent` strips the hardcoded slash from `@"Photos/"` so that when you try to use `directory` variable later, it does not include the slash that should separate it from `file`. A quick fix is to remove the hardcoded trailing slash when creating the `directory` variable and adding the slash into the `stringWithFormat` call between `%@%@` – Danny Sep 23 '16 at 20:15
  • 3
    You probably want to move `[fm contentsOfDirectoryAtPath:directory error:&error]` out of the `for` loop so it doesn't call that method on each iteration. Something like `NSArray *contents = [fm contentsOfDirectoryAtPath:documentsPath error:&error];` and `for (NSString *file in contents)` – strikerdude10 Jan 08 '17 at 21:04
16

if you want to remove files and the directory itself then use it without for loop

NSFileManager *fm = [NSFileManager defaultManager];
NSString *directory = [[self documentsDirectory] stringByAppendingPathComponent:@"Photos"];
NSError *error = nil;
BOOL success = [fm removeItemAtPath:cacheImageDirectory error:&error];
if (!success || error) {
    // something went wrong
}
beryllium
  • 29,669
  • 15
  • 106
  • 125
13

same for swift lovers:

let fm = FileManager.default
do {
  let folderPath = "...my/folder/path"
  let paths = try fm.contentsOfDirectory(atPath: folderPath)
  for path in paths
  {
    try fm.removeItem(atPath: "\(folderPath)/\(path)")
  }
} catch {
  print(error.localizedDescription)
}
Krešimir Prcela
  • 4,257
  • 33
  • 46
3

Most of the older answers have you use contentsOfDirectoryAtPath:error: which will work, but according to Apple:

"The preferred way to specify the location of a file or directory is to use the NSURL class"

so if you want to use NSURL instead you can use the method contentsOfDirectoryAtURL:includingPropertiesForKeys:options:error: so it would look something like this:

NSFileManager *fileManager = [NSFileManager defaultManager];
NSArray<NSURL*> *urls = [fileManager contentsOfDirectoryAtURL:directoryURL includingPropertiesForKeys:@[NSURLNameKey, NSURLIsDirectoryKey] options:NSDirectoryEnumerationSkipsHiddenFiles error:nil];

    for (NSURL *url in urls)
    {
        NSError *error = nil;
        BOOL success = [fileManager removeItemAtURL:url error:error];
        if (!success || error) {
            // something went wrong
        }
    }
strikerdude10
  • 663
  • 6
  • 15
0

Swift 4

  do {

        let destinationLocation:URL = ...

        if FileManager.default.fileExists(atPath: destinationLocation.path) {
            try! FileManager.default.removeItem(at: destinationLocation)
        }

    } catch {
    print("Error \(error.localizedDescription)")
    }
dimohamdy
  • 2,917
  • 30
  • 28
  • 2
    It shouldn't be force after try, if you are using catch. Also, you're trying to remove file by URL, not all files by path. – AVerguno Jan 16 '18 at 10:23
  • From Apple: "Attempting to predicate behavior based on the current state of the file system or a particular file on the file system is not recommended", meaning you shouldn't check if the file exists before removing it. You should just try and delete the file and then handle the error appropriately. Check out [the documentation](https://developer.apple.com/documentation/foundation/filemanager/1415645-fileexists) on `fileExists(atPath:)` for more info. – strikerdude10 Feb 03 '18 at 23:52