Quelle est la meilleure façon de joindre des fichiers après les avoir scindés?

73

Si j'ai un fichier volumineux et que je dois le scinder en morceaux de 100 Mo, je le ferai.

split -b 100m myImage.iso

Cela me donne généralement quelque chose comme

xaa
xab
xac
xad

Et pour les récupérer, j'ai utilisé

cat x* > myImage.iso

On dirait qu'il devrait y avoir un moyen plus efficace que de lire chaque ligne de code dans un groupe de fichiers avec catet de rediriger la sortie vers un nouveau fichier. C'est comme un moyen d'ouvrir deux fichiers, d'enlever le EOFmarqueur du premier et de les connecter, sans avoir à parcourir tout le contenu.

Windows / DOS a une commande de copie pour les fichiers binaires. L'aide indique que cette commande a été conçue pour pouvoir combiner plusieurs fichiers. Cela fonctionne avec cette syntaxe: ( /best pour le mode binaire)

copy /b file1 + file2 + file3 outputfile

Existe-t-il quelque chose de similaire ou un meilleur moyen de joindre des fichiers volumineux sous Linux que cat?

Mise à jour

Il semble que ce catsoit en fait le bon moyen et le meilleur moyen de joindre des fichiers. Heureux de savoir que j'utilisais toujours la bonne commande :) Merci à tous pour vos commentaires.

cwd
la source
22
Note latérale: Mieux vaut ne pas utiliser cat x*, car l'ordre des fichiers dépend de vos paramètres régionaux. Mieux vaut commencer à taper cat xqu'à appuyer sur Echap puis sur *- vous verrez l'ordre de fichiers étendu et pourrez le réorganiser.
rozcietrzewiacz
16
Au lieu de cela, cat x*vous pouvez envisager une expansion de l'accolade shell, cat xa{a..g}qui étend la séquence spécifiée à cat xaa xab xac xad xae xaf xag
Peter.O
3
@rozcietrzewiacz - pouvez-vous donner un exemple de la manière dont j'ajusterais les paramètres régionaux qui seraient rompus cat x*? Les nouveaux paramètres régionaux ne seront-ils pas également affectés de splitsorte que si splitet cat x*étaient utilisés sur le même système, ils fonctionneraient toujours?
cwd
3
« ouvrir deux fichiers, la suppression du marqueur EOF de la première, et en les reliant -. sans avoir à passer par tout le contenu » ... semble que vous avez besoin d'inventer un nouveau système de fichiers pour faire ce que vous voulez
JoelFan
6
@cwd: En regardant split.cdans GNU Coreutils, les suffixes sont construits à partir d' un réseau fixe de caractères: static char const *suffix_alphabet = "abcdefghijklmnopqrstuvwxyz";. Le suffixe ne serait pas affecté par les paramètres régionaux. (Mais je ne pense pas que n'importe quel endroit sain puisse réorganiser les lettres minuscules; même EBCDIC maintient leur ordre standard.)
Keith Thompson

Réponses:

50

C'est justement ce catpour quoi . Comme il s’agit de l’un des plus anciens outils GNU, il est très improbable qu’un autre outil le fasse plus rapidement / mieux. Et ce n'est pas une tuyauterie , c'est simplement une redirection de sortie.

rozcietrzewiacz
la source
Le cat x, then press Esctruc que vous avez mentionné est soigné .. Je cherchais quelque chose comme ça, merci ... bon commentaire et bonne réponse
Peter.O
2
De rien :) En outre, lorsque vous avez cette liste de fichiers sur la ligne de commande, vous pouvez utiliser Ctrl+Wpour couper un mot, puis Ctrl+Ypour le coller.
rozcietrzewiacz
cat signifie "concaténer"
JoelFan
4
.. et "catenate" dérivent d'un mot latin "catena" qui signifie "une chaîne" .. concaténer c'est joindre les maillons d'une chaîne. ... (et un peu plus loin, une courbe caténaire dévie également de "catena". C'est la façon dont une chaîne se bloque)
Peter.O
19

Sous la capuche

Il n'y a pas de moyen plus efficace que de copier le premier fichier, puis de copier le second, et ainsi de suite. DOS copyet catfaire ça.

Chaque fichier est stocké indépendamment des autres fichiers sur le disque. Presque tous les systèmes de fichiers conçus pour stocker des données sur un périphérique de type disque fonctionnent par blocs. Voici une présentation très simplifiée de ce qui se passe: le disque est divisé en blocs de, disons 1 Ko, et pour chaque fichier, le système d'exploitation stocke la liste des blocs qui le composent. La plupart des fichiers ne sont pas un nombre entier de blocs, le dernier bloc n'est donc que partiellement occupé. En pratique, les systèmes de fichiers disposent de nombreuses optimisations, telles que le partage du dernier bloc partiel entre plusieurs fichiers ou le stockage de «blocs 46798 à 47913» plutôt que de «bloc 46798, bloc 46799,…». Lorsque le système d'exploitation doit créer un nouveau fichier, il recherche des blocs libres. Les blocs ne doivent pas nécessairement être consécutifs: si seuls les blocs 4, 5, 98 et 178 sont libres, vous pouvez toujours stocker un fichier de 4 ko.

Vous pourriez prendre en charge des blocs partiels au milieu du fichier, mais cela ajouterait une complexité considérable, en particulier lorsque vous accédez à des fichiers de manière non séquentielle: pour passer au 10340e octet, vous ne pouvez plus passer au 100e octet du 11e bloc, vous devez vérifier la longueur de chaque bloc intervenant.

Avec l'utilisation de blocs, vous ne pouvez pas simplement joindre deux fichiers, car en général, le premier fichier se termine par un bloc. Bien sûr, vous pouvez avoir un cas particulier, mais uniquement si vous souhaitez supprimer les deux fichiers lors de la concaténation. Ce serait une manipulation très spécifique pour une opération rare. Un tel traitement spécial ne vit pas seul, car sur un système de fichiers typique, de nombreux fichiers sont accédés en même temps. Donc, si vous souhaitez ajouter une optimisation, vous devez bien réfléchir: que se passe-t-il si un autre processus lit l'un des fichiers en cause? Que se passe-t-il si quelqu'un essaie de concaténer A et B alors que quelqu'un concatène A et C? Etc. Au final, cette optimisation rare serait un énorme fardeau.

Globalement, vous ne pouvez pas rendre les fichiers joints plus efficaces sans faire de gros sacrifices ailleurs. Ça ne vaut pas le coup.

En se séparant et en rejoignant

splitet catsont des moyens simples de fractionner et de joindre des fichiers. splitprend en charge la production de fichiers nommés par ordre alphabétique, ce qui cat *fonctionne pour la jonction.

L’inconvénient de cette catadhésion est qu’elle n’est pas robuste contre les modes de défaillance courants. Si l'un des fichiers est tronqué ou manquant, catne vous plaindrez pas, vous aurez juste une sortie endommagée.

Certains utilitaires de compression produisent des archives en plusieurs parties, telles que zipsplitet rar -v. Ils ne sont pas très uniformes, car ils compressent et compressent (assemblent plusieurs fichiers en un) en plus du fractionnement (et inversement, décompressent et décompressent en plus de la jonction). Mais ils sont utiles en ce qu'ils vérifient que vous avez toutes les pièces et que toutes les pièces sont complètes.

Gilles, arrête de faire le mal
la source
8

On dirait qu’il devrait exister un moyen plus efficace que d’acheminer tout le contenu à travers le système stdin/stdout

Sauf que ce n'est pas vraiment ce qui se passe. Le shell connecte la sortie standard de cat directement au fichier ouvert, ce qui signifie que "passer par la sortie standard" est identique à l’écriture sur le disque.

Ignacio Vazquez-Abrams
la source
J'étais en train d'imaginer utiliser cat pour afficher plusieurs gigaoctets de code dans la console, puis de le capturer et de le stocker dans un fichier. C'est l'image mentale que j'ai pour ce qui doit se passer lorsque j'utilise cat et redirige la sortie que je ne peux pas voir. Il me semblait que s'il était possible d'ouvrir deux fichiers, de les connecter, puis de les fermer, ce serait plus efficace que de parcourir toutes les lignes de code cat. Merci de me faire savoir à propos de la connexion directe.
cwd
@cwd Il serait possible de concevoir un système de fichiers permettant de joindre deux fichiers de cette façon, mais cela compliquerait énormément la conception du système de fichiers. Vous optimiseriez cette opération au lieu de compliquer et de ralentir de nombreuses tâches courantes.
Gilles, arrête de faire le mal
@ Gilles - il serait intéressant d'en savoir plus sur les détails de bas niveau. Pour moi, lire tous les secteurs du disque dur sur plusieurs fichiers puis les transférer dans d'autres secteurs inutilisés du disque semble inefficace. Et je pense que les gros fichiers doivent parfois être stockés sur plusieurs blocs de secteurs libres, car il se peut qu’il n’y ait pas toujours assez de blocs côte à côte pour les stocker. Par conséquent, théoriquement, vous pouvez joindre des fichiers en un seul en supprimant le marqueur EOF et en pointant sur un groupe de secteurs au début du fichier suivant. * nix est puissant alors je me suis demandé s'il y avait un meilleur moyen que le chat.
cwd
@cwd Il n'y a pas de «marqueur EOF». Aucun système de fichiers moderne et sain ne fonctionne de la sorte, car il empêche certains caractères de figurer dans les fichiers (ou nécessite des codages complexes). Mais même s'il y avait un marqueur EOF, la plupart du temps, vous n'auriez pas le bon fichier après.
Gilles, arrête de faire le mal
Je voulais dire le concept du marqueur EOF et non un marqueur EOF réel. Sinon, si vous regardez les bits et les octets d'un fichier sur le disque dur, comment savez-vous où il se termine? Spécifiez-vous la longueur du fichier au début de celui-ci? Je parle d'une chose très bas niveau. Est-ce ce à quoi vous faites également référence?
CWD
3

Une fois, j’ai eu exactement ce problème: je voulais joindre des fichiers, mais je n’avais pas assez d’espace disque pour les stocker deux fois.

J'ai donc écrit un tas de programmes:

  • un pour "aspirer" un fichier en le lisant, en l'envoyant à stdout et, si c'est fini, en le supprimant
  • et un pour mettre les données en mémoire tampon "à la volée".

Cela m'a permis de faire quelque chose comme

partto sourcefile | mybuffer 128M >>cumufile

et donc supprimer le fichier source alors que 128M était encore non écrit. Un peu dangereux, mais si les données ne sont pas si précieuses, ou si elles existent ailleurs, c'est faisable.

Si nécessaire, je peux fournir la source.

glglgl
la source
0

Techniquement parlant, il s'agit d'un moyen d'accéder à l'intégralité du fichier sans avoir à lire ni à écrire l'intégralité du contenu. Il peut s'avérer utile pour les fichiers volumineux ou s'il reste peu d'espace:

$ mkfifo myImage.iso
$ cat xa{a..g} > myImage.iso &

Et puis utiliser myImage.iso, par exemple

$ md5sum myImage.iso

Bien que, bien sûr, il s’agisse d’ myImage.isoun fichier spécial (nommé pipe) et non d’un fichier ordinaire, il peut donc être utile ou non, selon ce que vous essayez de faire.

Golimar
la source
0

Division de fichiers

Split par taille

Si vous souhaitez diviser un gros fichier en petits fichiers et choisir le nom et la taille des petits fichiers de sortie, c'est ce qu'il vous faut.

split -b 500M videos\BigVideoFile.avi SmallFile.

De cette façon, vous choisissez de diviser un gros fichier en parties plus petites de 500 Mo. Aussi, vous voulez que les noms des fichiers de pièce soient SmallFile. Notez que vous avez besoin de point après le nom du fichier. Le résultat devrait être la génération de nouveaux fichiers comme ceci:

SmallFile.ab SmallFile.ad SmallFile.af SmallFile.ah SmallFile.aj
SmallFile.aa SmallFile.ac SmallFile.ae SmallFile.ag SmallFile.ai SmallFile.ak
...

Fractionner par nombre de lignes

De cette façon, vous diviserez le fichier texte en fichiers plus petits, limités à 50 lignes.

split -l 50 text_to_split.txt

Le résultat devrait ressembler à ceci:

xaa xab xac ...

Split By Bytes

Diviser en petits fichiers avec une taille personnalisée en octets:

split -b 2048 BigFile.mp4

Le résultat doit être similaire à celui obtenu en divisant par nombre de lignes .

Jointure de fichiers

Vous pouvez joindre des fichiers de deux manières. Le premier est:

cat SmallFile.* > OutputBigVideoFile.avi

ou avec:

cat SmallFile.?? > OutputBigVideoFile.avi

Remarque: lorsque vous joignez des fichiers, les petits fichiers ne doivent pas être endommagés. Tous les petits fichiers (parties) doivent également se trouver dans le même répertoire.

Nole
la source