Réponses:
Essayez ed
plutôt:
ed <<< $'1d\nwq' large_file
Si ce «grand» signifie environ 10 millions de lignes ou plus, mieux vaut l'utiliser tail
. N'est pas capable de montage sur place, mais ses performances rendent ce manque pardonnable:
tail -n +2 large_file > large_file.new
Modifiez pour afficher certaines différences de temps:
( awk
code de Jaypal ajouté pour avoir des temps d'exécution sur la même machine (CPU 2,2 GHz).)
bash-4.2$ seq 1000000 > bigfile.txt # further file creations skipped
bash-4.2$ time sed -i 1d bigfile.txt
time 0m4.318s
bash-4.2$ time ed -s <<< $'1d\nwq' bigfile.txt
time 0m0.533s
bash-4.2$ time perl -pi -e 'undef$_ if$.==1' bigfile.txt
time 0m0.626s
bash-4.2$ time { tail -n +2 bigfile.txt > bigfile.new && mv -f bigfile.new bigfile.txt; }
time 0m0.034s
bash-4.2$ time { awk 'NR>1 {print}' bigfile.txt > newfile.txt && mv -f newfile.txt bigfile.txt; }
time 0m0.328s
awk
et j'ai obtenu le résultat suivant -[jaypal:~/Temp] seq 1000000 > bigfile.txt [jaypal:~/Temp] time awk 'NR>1 {print}' bigfile.txt >newfile.txt real 0m0.649s user 0m0.601s sys 0m0.033s
awk
une performance plus proche de celle sed
de. (Remarque pour moi-même: ne vous attendez jamais - testez à la place.)
tail -n +2 bigfile.txt > bigfile.new && mv -f bigfile.new bigfile.txt;
j'utilise un seul fichier avec un verrou pour garder une trace d'une seule liste de tâches utilisée par plusieurs processus. J'ai commencé avec ce que l'affiche initiale utilisée: sed -i 1d large_file
. Cela provoquait le verrouillage du fichier pendant 1 à 2 secondes. Le tail/mv
combo se termine presque instantanément. Merci!
Il n'y a aucun moyen de supprimer efficacement des éléments au début d'un fichier. La suppression des données depuis le début nécessite la réécriture de tout le fichier.
La troncature à partir de la fin d'un fichier peut cependant être très rapide (le système d'exploitation n'a qu'à ajuster les informations sur la taille du fichier, éventuellement en supprimant les blocs non utilisés). Ce n'est généralement pas possible lorsque vous essayez de supprimer de la tête d'un fichier.
Cela pourrait théoriquement être "rapide" si vous supprimiez exactement un bloc / une étendue, mais il n'y a pas d'appels système pour cela, vous devrez donc vous fier à la sémantique spécifique au système de fichiers (si cela existe). (Ou avoir une certaine forme de décalage à l'intérieur du premier bloc / étendue pour marquer le début réel du fichier, je suppose. Je n'en ai jamais entendu parler non plus.)
La méthode la plus efficace, ne le faites pas! Si vous le faites, dans tous les cas, vous avez besoin du double du «grand» espace sur le disque et vous gaspillez les E / S.
Si vous êtes bloqué avec un gros fichier que vous souhaitez lire sans la 1ère ligne, attendez d'avoir besoin de le lire pour supprimer la 1ère ligne. Si vous devez envoyer le fichier de stdin à un programme, utilisez tail pour le faire:
tail -n +2 | your_program
Lorsque vous devez lire le fichier, vous pouvez en profiter pour supprimer la 1ère ligne, mais uniquement si vous disposez de l'espace nécessaire sur le disque:
tail -n +2 | tee large_file2 | your_program
Si vous ne pouvez pas lire depuis stdin, utilisez un fifo:
mkfifo large_file_wo_1st_line
tail -n +2 large_file > large_file_wo_1st_line&
your_program -i large_file_wo_1st_line
encore mieux si vous utilisez bash, profitez de la substitution de processus:
your_program -i <(tail -n +2 large_file)
Si vous avez besoin de rechercher dans le fichier, je ne vois pas de meilleure solution que de ne pas rester coincé avec le fichier en premier lieu. Si ce fichier a été généré par stdout:
large_file_generator | tail -n +2 > large_file
Sinon, il y a toujours la solution de substitution fifo ou process:
mkfifo large_file_with_1st_file
large_file_generator -o large_file_with_1st_file&
tail -n +2 large_file_with_1st_file > large_file_wo_1st_file
large_file_generator -o >(tail -n 2+ > large_file_wo_1st_file)
Vous pouvez utiliser Vim en mode Ex:
ex -sc '1d|x' large_file
1
sélectionner la première ligne
d
supprimer
x
sauver et fermer
C'est juste de la théorie, mais ...
Un système de fichiers personnalisé (implémenté à l'aide de FUSE ou d'un mécanisme similaire) pourrait exposer un répertoire dont le contenu est exactement le même qu'un répertoire déjà existant ailleurs, mais avec des fichiers tronqués comme vous le souhaitez. Le système de fichiers traduirait tous les décalages de fichiers. Ensuite, vous n'auriez pas à réécrire un fichier avec beaucoup de temps.
Mais étant donné que cette idée est très simple, à moins que vous n'ayez des dizaines de téraoctets de tels fichiers, la mise en œuvre d'un tel système de fichiers serait trop coûteuse / longue pour être pratique.
tail
, je préfère compter le temps pour faire à la fois supprimer la première ligne et remplacerbigfile.txt
parbigfile.new
.