Question osx: zip sélectivement grand nombre de fichiers: - option @ OK?


Je dois faire un fichier zip archivant ~ 100k fichiers à partir d'un répertoire contenant environ 500k fichiers. J'obtiens des erreurs "liste d'arguments trop longue" lorsque j'essaie les commandes évidentes:

zip archive.zip *pattern*.txt                        # fails
zip archive.zip `find . -name "*pattern*.txt"`       # fails

Une approche consiste à utiliser le -@ option pour alimenter une liste de fichiers via via stdin:

find . -name "*pattern*.txt" | zip -@ archive.zip

Cependant, le zip la page de manuel dit:

Si une liste de fichiers est spécifiée sous la forme - @ [Not on MacOS], zip prend la liste des fichiers d'entrée à partir de l'entrée standard au lieu de la ligne de commande.

C'est le "Not on MacOS" qui me bouscule. Je suis allé de l'avant et j'ai essayé le -@ option, et cela semble fonctionner; mais je me sens inquiet de savoir si cela fait vraiment le bon travail (archiver tous les fichiers, intact).

Voici mes questions:

  1. Pourquoi serait -@ ne pas être OK sur MacOS?
  2. Y a-t-il des versions de MacOS / bash / zip où cet avertissement est vrai, et d'autres où ce n'est pas le cas? Est-ce un avertissement obsolète, et si oui, où est la ligne de démarcation?
  3. Quelle serait une approche viable pour ce problème sans utiliser -@?

Notez que la solution donnée ici zip: liste d'arguments trop longue (80.000 fichiers au total) ne fonctionnera pas; Je dois archiver certains fichiers, pas tous, du répertoire.

J'utilise Mac OS 10.7.5. Voici quelques informations sur la version:

$ bash --version
GNU bash, version 3.2.48(1)-release (x86_64-apple-darwin11)
$ zip --version
This is Zip 3.0 (July 5th 2008), by Info-ZIP.
...
Compiled with gcc 4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2335.15.00) for Unix (Mac OS X) on Jun 24 2011.

4
2018-03-29 16:00


origine




Réponses:


Tout d'abord,

zip archive.zip `find . -name "*pattern*.txt"`

est jamais une bonne idée. Les noms de fichiers peuvent contenir des espaces, des caractères de nouvelle ligne, des parties pouvant être interprétées comme des commutateurs et ainsi de suite.

Pour effectuer une action pour chaque fichier trouvé, vous pouvez utiliser le -exec passer ou xargs.

find . -name "*pattern*.txt" -exec zip archive.zip {} +

ajoutera les fichiers un par un au fichier zip. Ici, {} symbolise le fichier actuellement traité.

Terminer le -exec argument avec un + au lieu de ; Cela permet à find de traiter plusieurs fichiers à la fois (autant que possible sans générer les mêmes erreurs que vous obtenez), ce qui devrait être considérablement plus rapide pour un grand nombre de fichiers.

find . -name "*pattern*.txt" -print0 | xargs -0 zip archive.zip

fait essentiellement la même chose. xargs traite plusieurs fichiers à la fois par défaut.

le -print0 basculer pour trouver et -0 passer à xargs les fait utiliser des caractères nuls comme séparateurs de fichiers pour traiter correctement les noms de fichiers étranges.

Je ne sais pas pourquoi le -@ n'est pas recommandé pour Mac OS1, mais find ... | zip -@ volonté ne pas gérer correctement les noms de fichiers étranges (en particulier les noms de fichiers contenant des caractères de nouvelle ligne). Cela est vrai quel que soit le système d'exploitation.


1 je suis devinant cela s'applique uniquement à Mac OS jusqu'à la version 9.x, étant donné que Mac OS utilise des retours chariot comme caractères de nouvelle ligne, tandis que zip -@ attend des sauts de ligne.


6
2018-03-29 16:23





Dennis avait raison, c'est une chose OS 9. J'ai regardé le code source de Zip 3.0. dans le macos/ répertoire de la plate-forme, il y a une note qui dit:

Ce port est destiné aux versions Mac antérieures à Mac OS X. Comme Mac OS X est basé sur Unix,   utilisez le port Unix pour Mac OS X. - 7 juin 2008

En outre, le zip.cfichier encapsule la déclaration de l'option de ligne de commande dans #ifndef MACOS. En d'autres termes, si j'utilisais le port "MacOS" de zip, la -@ l'option échouerait tout simplement.

Dennis a également fourni la réponse à "un moyen viable d'accomplir la tâche sans -@", à savoir,

find . -name "*pattern*.txt" -print0 | xargs -0 zip archive.zip

Je suis d'accord que c'est la meilleure façon de procéder pour être sûr contre les noms de fichiers "bizarres" (noms de fichiers avec espaces, nouvelles lignes, etc.). Cependant, il y a une pénalité de performance. xargs appellera zip plusieurs fois, avec un grand ensemble de noms de fichiers transmis comme paramètres de ligne de commande à chaque fois. zip va ajouter ces fichiers dans archive.zip sur chaque invocation. Mais zip devra lire le plus grand archive.zip sur chaque invocation, ce qui prend de plus en plus de temps à mesure que le travail progresse.

Si tu sais pour sûr que les noms de fichiers en question ne comportent pas de caractères pathologiques tels que des espaces ou des nouvelles lignes, puis le passage unique

find . -name "*pattern*.txt" | zip -@ archive.zip

sera plus rapide; et cela fonctionne très bien sur OS X, parce que zip sur OS X est en fait le port Unix. L'avertissement dans la page de manuel ne s'applique pas.


3
2018-03-30 14:31





Comme le montrent vos informations de version, le code de base (et donc probablement la documentation) est assez ancien, MacOS a beaucoup évolué entre-temps. En outre, la version est beaucoup plus récente que le code de base, il peut y avoir des modifications dans le code / la configuration de la construction qui n’a jamais été intégrée à la documentation.

Dans tous les cas, mieux vaut vérifier (avec un petit exemple peut-être) que la commande fonctionne et stocke réellement les fichiers qui lui sont demandés. Si c'est important, ne croyez pas les carrés de couleur avec des pièces manquantes sur des sites Internet aléatoires ...


0
2018-03-29 16:40