objective-c - varios - renombrar archivos en lote
¿Cambiar nombre de archivo en cacao? (5)
¿Cómo puedo cambiar el nombre de un archivo, manteniendo el archivo en el mismo directorio?
Tengo una cadena que contiene una ruta completa a un archivo y una cadena que contiene un nuevo nombre de archivo (y ninguna ruta), por ejemplo:
NSString *old_filepath = @"/Volumes/blah/myfilewithrubbishname.avi";
NSString *new_filename = @"My Correctly Named File.avi";
Sé sobre el método movePath:toPath:handler: , pero no puedo entrenar cómo construir la ruta del nuevo archivo ...
Básicamente estoy buscando el equivalente al siguiente código de 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)
Aquí hay un ejemplo más reciente para 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];
NSFileManager y NSWorkspace tienen métodos de manipulación de archivos, pero NSFileManager - (BOOL)movePath:(NSString *)source toPath:(NSString *)destination handler:(id)handler
es probablemente su mejor apuesta. Utilice los métodos de manipulación de ruta de NSString para obtener los nombres de archivo y carpeta correctos. Por ejemplo,
NSString *newPath = [[oldPath stringByDeletingLastPathComponent] stringByAppendingPathComponent:newFilename];
[[NSFileManager defaultManager] movePath:oldPath toPath:newPath handler:nil];
Ambas clases se explican bastante bien en los documentos, pero deje un comentario si hay algo que no entienda.
Para la formación de hielo en la parte superior, 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
Solo quería hacer 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 );
Vale la pena señalar que mover un archivo a sí mismo fallará. Tuve un método que reemplazó los espacios con guiones bajos e hice el nombre del archivo en minúscula y le cambié el nombre al nuevo nombre. Los archivos con una sola palabra en el nombre fallarían en el cambio de nombre, ya que el nuevo nombre sería idéntico en un sistema de archivos que no distinga mayúsculas y minúsculas.
La forma en que resolví esto fue hacer un cambio de nombre de dos pasos, primero cambiando el nombre del archivo por un nombre temporal y luego cambiándolo por el 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];