web-dev-qa-db-fra.com

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

Si j'ai un gros fichier et que je dois le diviser en morceaux de 100 mégaoctets, je le ferai

split -b 100m myImage.iso

Cela me donne généralement quelque chose comme

xaa
xab
xac
xad

Et pour les rassembler, j'utilise

cat x* > myImage.iso

Il semble qu'il devrait y avoir un moyen plus efficace que de lire chaque ligne de code d'un groupe de fichiers avec cat et de rediriger la sortie vers un nouveau fichier. Comme une façon d'ouvrir simplement deux fichiers, de supprimer le marqueur EOF 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 mentionne que cette commande a été conçue pour pouvoir combiner plusieurs fichiers. Il fonctionne avec cette syntaxe: (/b est pour le mode binaire)

copy /b file1 + file2 + file3 outputfile

Existe-t-il quelque chose de similaire ou une meilleure façon de joindre de gros fichiers sur Linux que cat?

Mise à jour

Il semble que cat soit en fait la bonne et la meilleure façon de joindre des fichiers. Heureux de savoir que j'utilisais la bonne commande depuis le début :) Merci à tous pour vos commentaires.

79
cwd

C'est exactement pour cela que cat a été conçu. Comme il s'agit de l'un des plus anciens outils GNU, je pense qu'il est très peu probable qu'un autre outil le fasse plus rapidement/mieux. Et ce n'est pas la tuyauterie - c'est seulement rediriger la sortie.

54
rozcietrzewiacz

Sous la capuche

Il n'y a pas de moyen plus efficace que de copier le premier fichier, puis de copier le deuxième fichier après, et ainsi de suite. DOS copy et cat le font.

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 de long, donc le dernier bloc n'est que partiellement occupé. En pratique, les systèmes de fichiers ont de nombreuses optimisations, comme le partage du dernier bloc partiel entre plusieurs fichiers ou le stockage des "blocs 46798 à 47913" plutôt que "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 être consécutifs: si seuls les blocs 4, 5, 98 et 178 sont libres, vous pouvez toujours stocker un fichier de 4 Ko. L'utilisation de blocs plutôt que de descendre au niveau de l'octet permet d'accélérer considérablement la recherche de blocs libres pour un fichier nouveau ou en croissance, et réduit les problèmes dus à la fragmentation lorsque vous créez ou agrandissez et supprimez ou réduisez un grand nombre de fichiers (laissant un nombre croissant de des trous).

Vous pouvez prendre en charge des blocs partiels en milieu de fichier, mais cela ajouterait une complexité considérable, en particulier lors de l'accès non séquentiel à des fichiers: pour passer au 10340e octet, vous ne pourriez plus sauter au 100e octet du 11e bloc, vous auriez pour vérifier la longueur de chaque bloc intermédiaire.

Étant donné l'utilisation de blocs, vous ne pouvez pas simplement joindre deux fichiers, car en général, le premier fichier se termine au milieu du bloc. Bien sûr, vous pourriez avoir un cas spécial, 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. Une telle gestion spéciale ne vit pas d'elle-même, car sur un système de fichiers typique, de nombreux fichiers sont accessibles en même temps. Donc, si vous souhaitez ajouter une optimisation, vous devez réfléchir attentivement: que se passe-t-il si un autre processus lit l'un des fichiers impliqués? Que se passe-t-il si quelqu'un essaie de concaténer A et B pendant que quelqu'un concatène A et C? Etc. Dans l'ensemble, cette optimisation rare serait un énorme fardeau.

Dans l'ensemble, vous ne pouvez pas rendre la jonction de fichiers plus efficace sans faire de gros sacrifices ailleurs. Ça ne vaut pas le coup.

Sur le fractionnement et la jonction

split et cat sont des moyens simples de fractionner et de joindre des fichiers. split s'occupe de produire des fichiers nommés par ordre alphabétique, afin que cat * fonctionne pour rejoindre.

Un inconvénient de cat pour la jonction est qu'il n'est pas robuste contre les modes de défaillance courants. Si l'un des fichiers est tronqué ou manquant, cat ne se plaindra pas, vous obtiendrez simplement une sortie endommagée.

Il existe des utilitaires de compression qui produisent des archives en plusieurs parties, telles que zipsplit et rar -v. Ils ne sont pas très unixy, car ils compressent et emballent (assemblent plusieurs fichiers en un seul) en plus de fractionner (et inversement décompresser et décompresser en plus de se joindre). Mais ils sont utiles car ils vérifient que vous avez toutes les pièces et que les pièces sont complètes.

Il semble qu'il devrait y avoir un moyen plus efficace que de canaliser tout le contenu via le stdin/stdout du système

Sauf que ce n'est pas vraiment ce qui se passe. Le shell connecte la sortie standard de catdirectement au fichier ouvert, ce qui signifie que "passer par la sortie standard" équivaut à écrire sur le disque.

8

J'ai eu une fois exactement ce problème: je voulais joindre certains fichiers, mais je n'avais pas assez d'espace disque pour les contenir deux fois.

J'ai donc écrit un tas de programmes:

  • un pour "aspirer" un fichier en le lisant, en l'envoyant à stdout et, s'il a terminé, en le supprimant
  • et un pour tamponner les données "à la volée".

Cela m'a permis de faire quelque chose comme

partto sourcefile | mybuffer 128M >>cumufile

et supprimant ainsi 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 qu'elles existent ailleurs, c'est faisable.

Si nécessaire, je peux fournir la source.

3
glglgl

division des fichiers

Fractionner par taille

Si vous voulez diviser un gros fichier en petits fichiers et choisir le nom et la taille des petits fichiers de sortie, c'est la voie.

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. Vous souhaitez également que les noms des fichiers de pièce soient SmallFile. Notez que vous avez besoin d'un point après le nom du fichier. Le résultat devrait être la génération de nouveaux fichiers comme celui-ci:

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

Fractionné 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 être quelque chose comme ceci:

xaa xab xac ...

Fractionner par octets

Fractionner en petits fichiers avec une taille personnalisée de petits fichiers en octets:

split -b 2048 BigFile.mp4

Le résultat doit être similaire au résultat de Fractionnement par nombre de lignes .

jonction 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 (partiels) doivent également se trouver dans le même répertoire.

1
Nole

Techniquement parlant, c'est un moyen d'accéder à l'intégralité du fichier sans avoir à lire et à écrire l'intégralité du contenu, et pourrait être utile pour les fichiers volumineux ou s'il reste peu d'espace:

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

Et puis utilisez myImage.iso, par exemple

$ md5sum myImage.iso

Bien sûr, myImage.iso est un fichier spécial (nommé pipe) et non un fichier normal, donc cela peut être utile ou non selon ce que vous essayez de faire.

0
golimar