1

NSTask を使用してアプリ内から zip コマンドを実行しています。圧縮するファイル/フォルダーを指すいくつかのパスが引数として渡されます。

問題は、-j オプションを指定しないと、最終的な zip が zip 内の不条理なファイルパスになってしまうことです (「/private/var/folders/A5/A5CusLQaEo4mop-reb-SYE+++TI/-Tmp-/9101A216-」など)。 5A6A-4CD6-A477-E4B86E007476-51228-00014BCB9514323F/myfile.rtf")。ただし、-j オプションを追加すると、ネストされたフォルダー内のどこかにファイルがある場合、常に名前の競合が発生します。

NSTask を実行する前にパスを設定してみました:

[[NSFileManager defaultManager] changeCurrentDirectoryPath:path];

zip のドキュメントが真実を語っていることを期待して:

デフォルトでは、zip はフル パス (現在のディレクトリからの相対パス)を格納します。

しかし、これは期待どおりに機能しませんでした。-j と -p と -r の設定を調整すると、さまざまな組み合わせで上記の問題が発生します。

質問:

次のような一連のディレクトリを取得するにはどうすればよいですか

  • /some/long/path/sub1/file1.txt
  • /some/long/path/sub2/file1.txt

それらをzipに圧縮し、その内容は次のとおりです

  • /sub1/file1.txt
  • /sub2/file1.txt

zip の微妙な点についてアドバイスをいただきありがとうございます。

- - -編集

追加するのを忘れていたもう1つのことは、渡される元のディレクトリが「パス」であるため、望ましい結果は期待される結果でもあるということです。

4

2 に答える 2

2

これは、複数のディレクトリを適切に処理できないという点で普遍的な解決策ではありませんが、内容が不明な単一のディレクトリ(つまり、混合ファイル/フォルダ/バンドル)に使用している解決策は、ディレクトリの内容を列挙することです。ディレクトリ全体を一度に圧縮するのではなく、zipの引数として個別に追加します。

具体的には:

+ (BOOL)zipDirectory:(NSURL *)directoryURL toArchive:(NSString *)archivePath;
{
//Delete existing zip
if ( [[NSFileManager defaultManager] fileExistsAtPath:archivePath] ) {
    [[NSFileManager defaultManager] removeItemAtPath:archivePath error:nil];
}

//Specify action
NSString *toolPath = @"/usr/bin/zip";

//Get directory contents
NSArray *pathsArray = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:[directoryURL path] error:nil];

//Add arguments
NSMutableArray *arguments = [[[NSMutableArray alloc] init] autorelease];
[arguments insertObject:@"-r" atIndex:0];
[arguments insertObject:archivePath atIndex:0];
for ( NSString *filePath in pathsArray ) {
    [arguments addObject:filePath]; //Maybe this would even work by specifying relative paths with ./ or however that works, since we set the working directory before executing the command
    //[arguments insertObject:@"-j" atIndex:0];
}

//Switch to a relative directory for working.
NSString *currentDirectory = [[NSFileManager defaultManager] currentDirectoryPath]; 
[[NSFileManager defaultManager] changeCurrentDirectoryPath:[directoryURL path]];
//NSLog(@"dir %@", [[NSFileManager defaultManager] currentDirectoryPath]);

//Create
NSTask *task = [[[NSTask alloc] init] autorelease];
[task setLaunchPath:toolPath];
[task setArguments:arguments];

//Run
[task launch];
[task waitUntilExit];

//Restore normal path
[[NSFileManager defaultManager] changeCurrentDirectoryPath:currentDirectory];

//Update filesystem
[[NSWorkspace sharedWorkspace] noteFileSystemChanged:archivePath];

return ([task terminationStatus] == 0);
}

繰り返しになりますが、これが防弾であるとは主張しません(そして改善が必要です)が、単一のフォルダーを正しく圧縮することはできます。

于 2011-06-15T15:46:24.057 に答える
2

それ以外の

[[NSFileManager defaultManager] changeCurrentDirectoryPath:path];

-[NSTask setCurrentDirectoryPath:]タスクを起動する前に使用します。例えば:

NSString *targetZipPath = @"/tmp/foo.zip";
NSArray *args = [NSArray arrayWithObjects:@"-r", targetZipPath,
    @"sub1", @"sub2", nil];
NSTask *task = [[NSTask alloc] init];
[task setLaunchPath:@"/usr/bin/zip"];
[task setArguments:args];

// set path to be the parent directory of sub1, sub2
[task setCurrentDirectoryPath:path];
…
于 2011-06-15T05:08:28.290 に答える