Je souhaite copier les 1 000 premières lignes d'un fichier texte contenant plus de 50 millions d'entrées dans un autre nouveau fichier et supprimer également ces lignes du fichier d'origine.
Existe-t-il un moyen de faire de même avec une seule commande Shell sous Unix?
head -1000 input > output && sed -i '1,+999d' input
Par exemple:
$ cat input
1
2
3
4
5
6
$ head -3 input > output && sed -i '1,+2d' input
$ cat input
4
5
6
$ cat output
1
2
3
head -1000 file.txt > first100lines.txt
tail --lines=+1001 file.txt > restoffile.txt
Par curiosité, j'ai trouvé une boîte avec une version GNU de sed
(v4.1.5) et testé les performances (non mises en cache) de deux approches suggérées jusqu'à présent, en utilisant un 11M fichier texte ligne:
$ wc -l input
11771722 input
$ time head -1000 input > output; time tail -n +1000 input > input.tmp; time cp input.tmp input; time rm input.tmp
real 0m1.165s
user 0m0.030s
sys 0m1.130s
real 0m1.256s
user 0m0.062s
sys 0m1.162s
real 0m4.433s
user 0m0.033s
sys 0m1.282s
real 0m6.897s
user 0m0.000s
sys 0m0.159s
$ time head -1000 input > output && time sed -i '1,+999d' input
real 0m0.121s
user 0m0.000s
sys 0m0.121s
real 0m26.944s
user 0m0.227s
sys 0m26.624s
Voici le Linux avec lequel je travaillais:
$ uname -a
Linux hostname 2.6.18-128.1.1.el5 #1 SMP Mon Jan 26 13:58:24 EST 2009 x86_64 x86_64 x86_64 GNU/Linux
Pour ce test, au moins, il semble que sed
soit plus lent que l'approche tail
(27 sec vs ~ 14 sec).
Il s'agit d'un monocylindre mais utilise quatre commandes atomiques:
head -1000 file.txt > newfile.txt; tail +1000 file.txt > file.txt.tmp; cp file.txt.tmp file.txt; rm file.txt.tmp
Approche Perl:
Perl -ne 'if($i<1000) { print; } else { print STDERR;}; $i++;' in 1> in.new 2> out && mv in.new in
En utilisant un tuyau:
cat en-tl.100.en | head -10