J'ai un fichier, foo.txt
, contenant les lignes suivantes:
a
b
c
Je veux une commande simple qui aboutisse au contenu de foo.txt
:
a
b
Utilisation de GNU sed
:
_sed -i '$ d' foo.txt
_
L'option _-i
_ n'existe pas dans les versions _GNU sed
_ 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 _head -n -1
_ au lieu de sed
.
MacOS:
Sur Mac OS X (à partir de 10.7.4), l’équivalent de la commande _sed -i
_ ci-dessus est
_sed -i '' -e '$ d' foo.txt
_
C'est de loin la solution la plus simple et la plus rapide, en particulier pour 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.
N'utilisez pas sed
pour supprimer les lignes situées en haut ou en bas d'un fichier - il est très lent si le fichier est volumineux.
J'ai eu du mal avec toutes les réponses ici parce que je travaillais avec un fichier ÉNORME (~ 300 Go) et aucune des solutions n'a été 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 mots: Déterminez la longueur du fichier que vous souhaitez utiliser (longueur du fichier moins la longueur de la dernière ligne, en utilisant bc
) et définissez cette position comme étant la fin du fichier (en dd
ing un octet de /dev/null
dessus).
C’est rapide parce que tail
commence à lire à partir de la fin, et dd
écrasera le fichier à la place plutôt que de copier (et d’analyser) chaque ligne du fichier, ce qui les autres solutions font.
NOTE: Ceci 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 le fichier en entier 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 la sortie standard ("la" la faire "), 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. Cela ressemble à la réponse de Yossi et s’inspire de celle-ci, mais évite d’utiliser quelques fonctions supplémentaires.
Si vous envisagez de les utiliser de manière répétée et souhaitez gérer les erreurs et certaines autres fonctionnalités, vous pouvez utiliser la commande poptail
ici: https://github.com/donm/evenmoreutils
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 voulez supprimer la dernière ligne du fichier d’entrée lui-même,
sed -i '' -e '$ d' foo.txt
Sur Mac, head -n-1 ne fonctionnera pas. Et j’essayais de trouver une solution simple [sans me soucier du temps de traitement] pour résoudre ce problème en utilisant seulement des commandes "tête" et/ou "queue".
J'ai essayé la séquence de commandes suivante et j'étais heureux de pouvoir la résoudre en utilisant simplement la commande "tail" [avec les options disponibles sur Mac]. Donc, si vous êtes sur Mac et que vous voulez utiliser uniquement "tail" pour résoudre ce problème, vous pouvez utiliser cette commande:
cat fichier.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: ceci affiche toutes les lignes à partir de la deuxième ligne dans son entrée
echo -e '$d\nw\nq'| ed foo.txt
awk 'NR>1{print buf}{buf = $0}'
Ce code dit essentiellement ce qui suit:
Pour chaque ligne après la première, imprimez la ligne mise en mémoire tampon
pour chaque ligne, réinitialiser le tampon
La mémoire tampon est décalée d’une ligne, d’où l’impression des lignes 1 à n-1.
awk "NR != `wc -l < text.file`" text.file |> text.file
Cet extrait fait l'affaire.
Voici comment vous pouvez le faire manuellement (personnellement, j'utilise beaucoup cette méthode lorsque je dois 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 se positionne sur la dernière ligne du fichier.
Maintenant, appuyez deux fois sur d
sur votre clavier. Cela fera exactement ce que vous voulez - supprimez la dernière ligne. Ensuite, appuyez sur :
suivi de x
, puis appuyez sur Enter
. Cela enregistrera les modifications et vous ramènera à l'environnement de ligne de commande. Maintenant, la dernière ligne a été supprimée avec succès.
Ces deux solutions sont ici sous d'autres formes. J'ai trouvé cela un peu plus pratique, clair et utile:
En utilisant 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}