2009-05-16 26 views
24

¿Cómo cambiaría el nombre de un archivo, manteniendo el archivo en el mismo directorio?¿Cambiar el nombre del archivo en Cocoa?

tengo una cadena que contiene una ruta de acceso completa a un archivo y una cadena que contiene un nuevo nombre de archivo (y no hay camino), por ejemplo:

NSString *old_filepath = @"/Volumes/blah/myfilewithrubbishname.avi"; 
NSString *new_filename = @"My Correctly Named File.avi"; 

que sé sobre el método de NSFileManager movePath:toPath:handler:, pero no puedo entrenamiento de cómo construir el camino del nuevo archivo ..

Básicamente estoy buscando el equivalente al siguiente código Python:

>>> import os 
>>> old_filepath = "/Volumes/blah/myfilewithrubbishname.avi" 
>>> new_filename = "My Correctly Named File.avi" 
>>> dirname = os.path.split(old_filepath)[0] 
>>> new_filepath = os.path.join(dirname, new_filename) 
>>> print new_filepath 
/Volumes/blah/My Correctly Named File.avi 
>>> os.rename(old_filepath, new_filepath) 

Respuesta

36

NSFileManager y NSWorkspace tienen métodos de manipulación de archivos, pero - (BOOL)movePath:(NSString *)source toPath:(NSString *)destination handler:(id)handler de NSFileManager es probablemente la mejor opción. Use los métodos de manipulación de rutas de NSString para obtener los nombres de archivos y carpetas correctos. Por ejemplo, se explican

NSString *newPath = [[oldPath stringByDeletingLastPathComponent] stringByAppendingPathComponent:newFilename]; 
[[NSFileManager defaultManager] movePath:oldPath toPath:newPath handler:nil]; 

Ambas clases bastante bien en la documentación, pero dejan un comentario si hay algo que no entiende.

+0

Aha, me faltaban los métodos de la cadenaBy___PathComponentes, gracias! – dbr

+18

movePath: toPath: handler: está en desuso en favor de moveItemAtPath: toPath: error :, que, si falla, le dirá * por qué * falló. –

+0

maravillosa respuesta –

8

Solo quería que esto sea más fácil de entender para un novato. Aquí está todo el código:

NSString *oldPath = @"/Users/brock/Desktop/OriginalFile.png"; 
NSString *newFilename = @"NewFileName.png"; 

NSString *newPath = [[oldPath stringByDeletingLastPathComponent] stringByAppendingPathComponent:newFilename]; 
[[NSFileManager defaultManager] movePath:oldPath toPath:newPath handler:nil]; 

NSLog(@"File renamed to %@", newFilename); 
14

Vale la pena señalar que mover un archivo a sí mismo fallará. Tenía un método que reemplazaba espacios con guiones bajos e hizo que el nombre del archivo fuera minúsculo y renombré el archivo al nuevo nombre. Los archivos con una sola palabra en el nombre no cambiarían el nombre ya que el nuevo nombre sería idéntico en un sistema de archivos que no distingue mayúsculas de minúsculas.

La forma en que resolví esto fue hacer un cambio de nombre de dos pasos, primero renombrar el archivo a un nombre temporal y luego cambiarle el nombre al nombre deseado.

Algunos pseudocódigo explicando esto:

NSString *source = @"/FILE.txt"; 
NSString *newName = [[source lastPathComponent] lowercaseString]; 
NSString *target = [[oldPath stringByDeletingLastPathComponent] stringByAppendingPathComponent:newName]; 

[[NSFileManager defaultManager] movePath:source toPath:target error:nil]; // <-- FAILS 

La solución:

NSString *source = @"/FILE.txt"; 
NSString *newName = [[source lastPathComponent] lowercaseString]; 

NSString *temp = [[oldPath stringByDeletingLastPathComponent] stringByAppendingPathComponent:[NSString stringWithFormat:@"%@-temp", newName]]; 
NSString *target = [[oldPath stringByDeletingLastPathComponent] stringByAppendingPathComponent:newName]; 

[[NSFileManager defaultManager] movePath:source toPath:temp error:nil]; 
[[NSFileManager defaultManager] movePath:temp toPath:target error:nil]; 
+1

Bueno, yo diría que simplemente comprobar si los nombres nuevos y viejos son iguales antes de moverlos es probablemente mejor para el rendimiento que mover un archivo dos veces. – 11684

+1

Pero eso no lograría el objetivo de cambiar el caso del nombre del archivo. –

4

aquí está un ejemplo más reciente de iOS, el método NSFileManager es un poco diferente:

NSString *newFilename = [NSString stringWithFormat:@"%@.m4a", newRecording.title]; 

NSString *newPath = [[newRecording.localPath stringByDeletingLastPathComponent] stringByAppendingPathComponent:newFilename]; 
[[NSFileManager defaultManager] moveItemAtPath:newRecording.localPath toPath:newPath error:nil]; 
0

Para la guinda del pastel, una categoría en NSFileManager:

@implementation NSFileManager (FileManipulations) 


- (void)changeFileNamesInDirectory:(NSString *)directory changeBlock:(NSString * (^) (NSString *fileName))block 
{ 
    NSString *inputDirectory = directory; 

    NSFileManager *fileManager = [NSFileManager new]; 

    NSArray *fileNames = [fileManager contentsOfDirectoryAtPath:inputDirectory error:nil]; 
    for (NSString *fileName in fileNames) { 

     NSString *newFileName = block(fileName); 

     NSString *oldPath = [NSString stringWithFormat:@"%@/%@", inputDirectory, oldFileName]; 
     // move to temp path so case changes can happen 
     NSString *tempPath = [NSString stringWithFormat:@"%@-tempName", oldPath]; 
     NSString *newPath = [[oldPath stringByDeletingLastPathComponent] stringByAppendingPathComponent:newFileName]; 

     NSError *error = nil; 
     [fileManager moveItemAtPath:oldPath toPath:tempPath error:&error]; 
     if (error) { 
      NSLog(@"%@", [error localizedDescription]); 
      return; 
     } 
     [fileManager moveItemAtPath:tempPath toPath:newPath error:&error]; 
     if (error) { 
      NSLog(@"%@", [error localizedDescription]); 
     } 
    } 
} 


@end 
Cuestiones relacionadas