2011-06-15 3 views
1

J'exécute une commande zip à partir de mon application en utilisant NSTask. Il est passé en arguments certains chemins qui pointent vers les fichiers/dossiers à compresser. Le problème est que sans l'option -j, le zip final se termine par des chemins de fichier absurdes à l'intérieur du zip, (comme "/ private/var/folders/A5/A5CusLQaEo4mop-reb-SYE +++ TI/-Tmp -/9101A216-5A6A-4CD6-A477-E4B86E007476-51228-00014BCB9514323F/myfile.rtf "). Cependant, si j'ajoute l'option -j, puis-je utiliser en permanence dans les collisions de noms si un fichier ne importe où dans un dossier profondément imbriqué aZip à partir de la ligne de commande - comment rogner les éléments de chemin

J'ai tenté de mettre sur le chemin avant d'exécuter la NSTask:

[[NSFileManager defaultManager] changeCurrentDirectoryPath:path]; 

dans l'espoir que la documentation zip dit la vérité:

par défaut, zip stocke le chemin complet (par rapport au répertoire courant)

Mais cela n'a pas fonctionné comme prévu. Ajuster les paramètres de -j et -p et -r produit simplement les problèmes mentionnés ci-dessus dans différentes combinaisons.

QUESTION:

Comment puis-je prendre un ensemble de répertoires comme

  • /some/long/path/sub1/file1.txt
  • /some/long/chemin/SUB2/fichier1 txt

et les zip dans un zip dont le contenu est

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

Merci pour tout conseil sur les subtilités de zip.

----- EDIT

Une autre chose que j'oublié d'ajouter que le répertoire d'origine étant passé est « chemin », de sorte que le résultat souhaité est également à l'esprit le résultat attendu.

Répondre

2

Ce n'est pas une solution universelle dans la mesure où il ne sera pas gérer plusieurs répertoires bien, mais la solution que je utilise un répertoire unique des contenus inconnus (par exemple, les fichiers mixtes/dossiers/bundles) consiste à énumérer le contenu du répertoire et à les ajouter individuellement en tant qu'arguments à compresser, plutôt que de simplement compresser le répertoire entier en une fois.

Plus précisément:

+ (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); 
} 

Encore une fois, je ne prétends pas que c'est l'épreuve des balles (et je serais ravi des améliorations), mais il ne fonctionne pas correctement à passer comme un éclair tout seul dossier.

2

Au lieu de

[[NSFileManager defaultManager] changeCurrentDirectoryPath:path]; 

utilisation -[NSTask setCurrentDirectoryPath:] avant le lancement de la tâche. Par exemple:

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]; 
… 
+0

Cela ressemble à une excellente solution, merci. Je ne sais pas comment j'ai raté la méthode de répertoire spécifique à la tâche. Je n'ai pas testé cela depuis que j'ai réussi à trouver un autre itinéraire. Une autre question que j'ai à ce sujet, et sur la solution que je fournis est, que se passe-t-il si les deux répertoires n'ont pas de parent commun? – SG1

+0

@ SG1 Je ne pense pas que l'utilitaire de ligne de commande 'zip' puisse le faire si les répertoires n'ont pas de parent commun. Vous pouvez copier les répertoires dans un répertoire, même si ce n'est pas l'idéal. –

Questions connexes