2009-05-16 15 views
24

Come rinominare un file, mantenendo il file nella stessa directory?Rinomina file in Cocoa?

ho una stringa contenente un percorso completo di un file, e una stringa contenente un nuovo nome di file (e nessun percorso), per esempio:

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

che so il metodo di NSFileManager movePath:toPath:handler:, ma non posso allenamento come costruire il percorso del nuovo file di ..

Fondamentalmente sto cercando l'equivalente al seguente codice 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) 

risposta

36

NSFileManager e NSWorkspace hanno entrambi metodi di manipolazione dei file, ma lo - (BOOL)movePath:(NSString *)source toPath:(NSString *)destination handler:(id)handler di NSFileManager è probabilmente la soluzione migliore. Utilizzare i metodi di manipolazione del percorso di NSString per ottenere i nomi di file e cartelle giusti. Ad esempio,

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

Entrambe le classi sono spiegate abbastanza bene nella documentazione, ma lasciano un commento, se c'è qualcosa che non capisci.

+0

Aha, mi mancavano i metodi stringa By___PathComponents, grazie! – dbr

+18

movePath: toPath: handler: è deprecato a favore di moveItemAtPath: toPath: error :, che, se fallisce, in realtà ti dirà * perché * non è riuscito. –

+0

meravigliosa risposta –

8

Volevo solo renderlo più facile da capire per un principiante. Ecco tutto il codice:

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 notare che lo spostamento di un file su se stesso fallirà. Avevo un metodo che sostituiva gli spazi con caratteri di sottolineatura e rendeva il nome del file in minuscolo e rinominava il file con il nuovo nome. I file con una sola parola nel nome non avrebbero cambiato il nome poiché il nuovo nome sarebbe identico su un file system senza distinzione tra maiuscole e minuscole.

Il modo in cui ho risolto questo era di eseguire una ridenominazione in due passaggi, prima di rinominare il file con un nome temporaneo e di rinominarlo con il nome desiderato.

Alcuni pseudocodice spiegare questo:

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 soluzione:

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

Beh, direi che controllare solo se i nuovi e vecchi nomi sono uguali prima di spostarsi è probabilmente meglio per le prestazioni che spostare un file due volte. – 11684

+1

Ma questo non avrebbe portato a termine l'obiettivo di cambiare il caso del nome del file. –

4

ecco un esempio più recente di iOS, il metodo NSFileManager è un po 'diverso:

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

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

Per la ciliegina sulla torta, una categoria su 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