Переименовать файл в Cocoa?

Как бы я переименовал файл, сохраняя файл в том же каталоге?

У меня есть строка, содержащая полный путь к файлу, и строка, содержащая новое имя файла (без пути), например:

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

Я знаю о movePath:toPath:handler:, но я не могу понять, как создать новый путь к файлу..

В основном я ищу эквивалент следующего кода 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)

person dbr    schedule 16.05.2009    source источник


Ответы (5)


У NSFileManager и NSWorkspace есть методы манипулирования файлами, но - (BOOL)movePath:(NSString *)source toPath:(NSString *)destination handler:(id)handler NSFileManager, вероятно, лучший выбор. Используйте методы манипуляции с путями NSString, чтобы получить правильные имена файлов и папок. Например,

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

Оба класса довольно хорошо объяснены в документации, но оставьте комментарий, если вам что-то непонятно.

person Marc Charbonneau    schedule 16.05.2009
comment
Ага, мне не хватало методов stringBy___PathComponents, спасибо! - person dbr; 17.05.2009
comment
movePath:toPath:handler: устарел в пользу moveItemAtPath:toPath:error:, который в случае сбоя фактически расскажет вам, почему это не удалось. - person Peter Hosey; 17.05.2009
comment
Привет, @Marc Charbonneau. Я знаю, что этот ответ замечательный. Но вопрос в том, что я хочу, чтобы новое имя файла имело /.Example, я хочу переименовать 123.mp3 в 12/3.mp3, это не сработает. Я думаю, NSFileManager см. / как путь. - person Vienta; 20.06.2014
comment
Устарело, начиная с OS X 10.5 - person Aviram Netanel; 20.04.2016

Стоит отметить, что переместить файл на себя не удастся. У меня был метод, который заменял пробелы символами подчеркивания, делал имя файла строчным и переименовывал файл в новое имя. Файлы, содержащие только одно слово в имени, переименовать не удастся, так как новое имя будет идентичным в файловой системе, нечувствительной к регистру.

Я решил это путем двухэтапного переименования, сначала переименовав файл во временное имя, а затем переименовав его в предполагаемое имя.

Некоторый псевдокод, объясняющий это:

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

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

Решение:

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];
person Martin Gordon    schedule 06.06.2009
comment
Что ж, я бы сказал, что простая проверка равенства нового и старого имен перед перемещением, вероятно, лучше для производительности, чем перемещение файла дважды. - person 11684; 31.03.2013
comment
Но это не поможет изменить регистр имени файла. - person Joe Strout; 07.08.2013

Я просто хотел сделать это более понятным для новичка. Вот весь код:

    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 );
person Brock Woolf    schedule 17.05.2009

вот более свежий пример для iOS, метод NSFileManager немного отличается:

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

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

Для обледенения сверху, категория на 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
person Alec    schedule 02.09.2013