J'ai un grand nombre de fichiers, dont certains sont très longs. Je voudrais les tronquer à une certaine taille s'ils sont plus grands en supprimant la fin du fichier. Mais je veux seulement supprimer des lignes entières. Comment puis-je faire ceci? Cela ressemble au genre de chose qui serait gérée par la chaîne d'outils Linux, mais je ne connais pas la bonne commande.
Par exemple, disons que j'ai un fichier de 120 000 octets avec des lignes de 300 octets et que j'essaie de le tronquer à 10 000 octets. Les 33 premières lignes doivent rester (9900 octets) et les autres doivent être coupées. Je ne veux pas couper à 10 000 octets exactement, car cela laisserait une ligne partielle.
Bien sûr, les fichiers sont de longueurs différentes et les lignes ne sont pas toutes de la même longueur.
Idéalement, les fichiers résultants seraient rendus légèrement plus courts plutôt que légèrement plus longs (si le point d'arrêt est sur une longue ligne) mais ce n'est pas trop important, cela pourrait être un peu plus long si cela était plus facile. Je voudrais que les modifications soient apportées directement aux fichiers (enfin, peut-être le nouveau fichier copié ailleurs, l'original supprimé et le nouveau fichier déplacé, mais c'est la même chose du POV de l'utilisateur). Une solution qui redirige les données vers un tas d'endroits puis revient invite à la possibilité de corrompre le fichier et j'aimerais éviter cela ...
la source
Réponses:
La
sed
/wc
complexité peut être évitée dans les réponses précédentes si elleawk
est utilisée. En utilisant l'exemple fourni par OP (montrant les lignes complètes avant 10000 octets):Affiche également la ligne complète contenant 10000e octet si cet octet n'est pas en fin de ligne:
La réponse ci-dessus suppose:
\n
). Pour les fichiers texte Dos / Windows (\r\n
), passezlength() + 1
àlength() + 2
LC_CTYPE=C
pour forcer l'interprétation au niveau des octets.la source
L'
sed
approche est bonne, mais faire une boucle sur toutes les lignes ne l'est pas. Si vous savez combien de lignes vous souhaitez conserver (pour avoir un exemple, j'utilise 99 ici), vous pouvez le faire comme ceci:Explication:
sed
est un processeur d'expression régulière. Avec l'option-i
donnée, il traite un fichier directement ("en ligne") - au lieu de simplement le lire et écrire les résultats sur la sortie standard.100,$
signifie simplement "de la ligne 100 à la fin du fichier" - et est suivi de la commanded
, que vous avez probablement deviné correctement pour "supprimer". Donc, en bref, la commande signifie: "Supprimer toutes les lignes de la ligne 100 jusqu'à la fin du fichier de monfichier.txt". 100 est la première ligne à supprimer, car vous souhaitez conserver 99 lignes.Edit: Si, d'autre part, il y a des fichiers journaux où vous souhaitez conserver par exemple les 100 dernières lignes:
Qu'est-ce qui se passe ici:
[ $(wc -l myfile.txt) -gt 100 ]
: procédez comme suit uniquement si le fichier contient plus de 100 lignes$((100 - $(wc -l myfile.txt|awk '{print $1}')))
: calculer le nombre de lignes à supprimer (c'est-à-dire toutes les lignes du fichier sauf les (dernières) 100 à conserver)1, $((..)) d
: supprime toutes les lignes de la première à la ligne calculéeEDIT: comme la question vient d'être modifiée pour donner plus de détails, je vais également inclure cette information supplémentaire avec ma réponse. Les faits ajoutés sont:
A partir de ces données, il est possible de calculer le nombre de lignes à conserver comme "/", ce qui avec l'exemple signifierait 33 lignes. Le terme shell pour le calcul:
$((size_to_remain / linesize))
(au moins sous Linux utilisant Bash, le résultat est un entier). La commande ajustée se lirait maintenant:Comme les tailles sont connues à l'avance, il n'y a plus besoin de calcul intégré à la
sed
commande. Mais pour plus de flexibilité, à l'intérieur de certains scripts shell, on peut utiliser des variables.Pour un traitement conditionnel basé sur la taille du fichier, on peut utiliser la structure "test" suivante:
ce qui signifie: "si la taille de
$file
dépasse 100 Ko, faites ..." (ls -lk
répertorie la taille du fichier en Ko à la position 5, doncawk
est utilisé pour extraire exactement cela).la source
head -n
.A défaut de trouver une commande pour ce faire, j'ai écrit un script rapide (non testé):
la source
Vous pouvez utiliser la commande linux sed pour supprimer des lignes d'un fichier. La commande suivante supprime la dernière ligne de filename.txt:
Avec awk ou find, vous pouvez rechercher un motif correspondant à votre commande sed. D'abord, vous recherchez avec awk ou recherchez les fichiers que vous souhaitez raccourcir, puis vous pouvez supprimer les lignes avec sed.
la source
J'ai fait quelque chose de similaire avec la queue. Pour ne conserver que les 10 000 dernières lignes dans ce cas:
la source