J'ai un fichier foo.txt
, contenant les lignes suivantes:
a
b
c
Je veux une commande simple qui se traduit par le contenu de foo.txt
:
a
b
J'ai un fichier foo.txt
, contenant les lignes suivantes:
a
b
c
Je veux une commande simple qui se traduit par le contenu de foo.txt
:
a
b
Réponses:
En utilisant GNU sed
:
sed -i '$ d' foo.txt
L' -i
option n'existe pas dans les GNU sed
versions antérieures à 3,95, vous devez donc l'utiliser comme filtre avec un fichier temporaire:
cp foo.txt foo.txt.tmp
sed '$ d' foo.txt.tmp > foo.txt
rm -f foo.txt.tmp
Bien sûr, dans ce cas, vous pouvez également utiliser à la head -n -1
place de sed
.
MacOS:
Sur Mac OS X (à partir de 10.7.4), l'équivalent de la sed -i
commande ci-dessus est
sed -i '' -e '$ d' foo.txt
$ d
une expression régulière. C'est une commande sed. d
est la commande pour supprimer une ligne, tandis que $
signifie "la dernière ligne du fichier". Lorsque vous spécifiez un emplacement (appelé "plage" dans le jargon sed) avant une commande, cette commande n'est appliquée qu'à l'emplacement spécifié. Ainsi, cette commande dit explicitement "dans la plage de la dernière ligne d'un fichier, supprimez-le". Assez lisse et droit au but, si vous me demandez.
C'est de loin la solution la plus rapide et la plus simple, notamment sur les gros fichiers:
head -n -1 foo.txt > temp.txt ; mv temp.txt foo.txt
si vous souhaitez supprimer la ligne supérieure, utilisez ceci:
tail -n +2 foo.txt
ce qui signifie que les lignes de sortie commencent à la ligne 2.
Ne pas utiliser sed
pour supprimer des lignes du haut ou du bas d'un fichier - c'est très très lent si le fichier est volumineux.
head -n -1 foo.txt
suffit
brew install coreutils
(utilitaires principaux GNU) et utiliser à la ghead
place de head
.
FILE=$1; TAIL=$2; head -n -${TAIL} ${FILE} > temp ; mv temp ${FILE}
Exécutez-le pour supprimer 4 lignes par exemple de mon fichier comme: ./TAILfixer myfile 4
bien sûr, rendez-le d'abord exécutable parchmod +x TAILfixer
sed
, cette commande est aussi sacrément lente
J'ai eu des problèmes avec toutes les réponses ici parce que je travaillais avec un fichier ÉNORME (~ 300 Go) et aucune des solutions n'était mise à l'échelle. Voici ma solution:
dd if=/dev/null of=<filename> bs=1 seek=$(echo $(stat --format=%s <filename> ) - $( tail -n1 <filename> | wc -c) | bc )
En d'autres termes: déterminez la longueur du fichier avec bc
lequel vous souhaitez vous retrouver (longueur du fichier moins longueur de la dernière ligne, à l'aide de ) et définissez cette position comme étant la fin du fichier (en dd
ingérant un octet de /dev/null
sur il).
Ceci est rapide car tail
commence la lecture depuis la fin et dd
écrase le fichier en place plutôt que de copier (et d'analyser) chaque ligne du fichier, ce que font les autres solutions.
REMARQUE: cela supprime la ligne du fichier en place! Faites une sauvegarde ou un test sur un fichier factice avant de l'essayer sur votre propre fichier!
Pour supprimer la dernière ligne d'un fichier sans lire l'intégralité du fichier ni réécrire quoi que ce soit , vous pouvez utiliser
tail -n 1 "$file" | wc -c | xargs -I {} truncate "$file" -s -{}
Pour supprimer la dernière ligne et également l'imprimer sur stdout ("pop" it), vous pouvez combiner cette commande avec tee
:
tail -n 1 "$file" | tee >(wc -c | xargs -I {} truncate "$file" -s -{})
Ces commandes peuvent traiter efficacement un très gros fichier. Ceci est similaire et inspiré par la réponse de Yossi, mais cela évite d'utiliser quelques fonctions supplémentaires.
Si vous allez les utiliser à plusieurs reprises et que vous souhaitez gérer les erreurs et d'autres fonctionnalités, vous pouvez utiliser la poptail
commande ici:
https://github.com/donm/evenmoreutils
truncate
n'est pas disponible sur OS X par défaut. Mais il est facile à installer à l' aide Brew: brew install truncate
.
Utilisateurs Mac
si vous voulez seulement que la dernière ligne soit supprimée sans changer le fichier lui-même
sed -e '$ d' foo.txt
si vous souhaitez supprimer la dernière ligne du fichier d'entrée
sed -i '' -e '$ d' foo.txt
-i ''
indique à sed de modifier le fichier sur place, tout en conservant une sauvegarde dans un fichier avec l'extension fournie en paramètre. Le paramètre étant une chaîne vide, aucun fichier de sauvegarde n'est créé. -e
indique à sed d'exécuter une commande. La commande $ d
signifie: trouver la dernière ligne ( $
) et la supprimer ( d
).
Sur Mac, head -n -1 ne fonctionnera pas. Et, j'essayais de trouver une solution simple [sans se soucier du temps de traitement] pour résoudre ce problème uniquement en utilisant les commandes "head" et / ou "tail".
J'ai essayé la séquence de commandes suivante et j'étais heureux de pouvoir le résoudre en utilisant simplement la commande "tail" [avec les options disponibles sur Mac]. Donc, si vous êtes sur Mac et que vous souhaitez utiliser uniquement "tail" pour résoudre ce problème, vous pouvez utiliser cette commande:
cat file.txt | queue -r | queue -n +2 | queue -r
1> tail -r: inverse simplement l'ordre des lignes dans son entrée
2> tail -n +2: cela imprime toutes les lignes à partir de la deuxième ligne dans son entrée
ghead -n -1
awk 'NR>1{print buf}{buf = $0}'
Essentiellement, ce code dit ce qui suit:
Pour chaque ligne après la première, imprimez la ligne en mémoire tampon
pour chaque ligne, réinitialisez le tampon
Le tampon est décalé d'une ligne, vous finissez donc par imprimer les lignes 1 à n-1
awk "NR != `wc -l < text.file`" text.file |> text.file
Cet extrait fait l'affaire.
Ces deux solutions sont ici sous d'autres formes. Je les ai trouvées un peu plus pratiques, claires et utiles:
Utilisation de dd:
BADLINESCOUNT=1
ORIGINALFILE=/tmp/whatever
dd if=${ORIGINALFILE} of=${ORIGINALFILE}.tmp status=none bs=1 count=$(printf "$(stat --format=%s ${ORIGINALFILE}) - $(tail -n${BADLINESCOUNT} ${ORIGINALFILE} | wc -c)\n" | bc )
/bin/mv -f ${ORIGINALFILE}.tmp ${ORIGINALFILE}
Utilisation de tronquer:
BADLINESCOUNT=1
ORIGINALFILE=/tmp/whatever
truncate -s $(printf "$(stat --format=%s ${ORIGINALFILE}) - $(tail -n${BADLINESCOUNT} ${ORIGINALFILE} | wc -c)\n" | bc ) ${ORIGINALFILE}
sed '$d' ~/path/to/your/file/name
sed -i '' -e '$ d' ~/path/to/your/file/name
Voici comment vous pouvez le faire manuellement (j'utilise personnellement cette méthode beaucoup lorsque j'ai besoin de supprimer rapidement la dernière ligne d'un fichier):
vim + [FILE]
Ce +
signe signifie que lorsque le fichier est ouvert dans l'éditeur de texte vim, le curseur sera positionné sur la dernière ligne du fichier.
Maintenant, appuyez simplement d
deux fois sur votre clavier. Cela fera exactement ce que vous voulez: supprimez la dernière ligne. Après cela, appuyez :
sur x
, puis sur Enter
. Cela enregistrera les modifications et vous ramènera au shell. Maintenant, la dernière ligne a été supprimée avec succès.
sed -i
commande ci-dessus estsed -i '' -e '$ d' foo.txt
. De plus,head -n -1
ne fonctionnera pas actuellement sur un Mac.