Linux / Commande tac : afficher les lignes dans l’ordre inverse

tac affiche les enregistrements d'une entrée du dernier au premier. Comme le séparateur par défaut est le retour à la ligne, il inverse normalement l'ordre des lignes tout en conservant l'ordre des caractères à l'intérieur de chacune. Il convient pour relire un fichier depuis sa fin ; il ne trie pas les valeurs et n'interprète pas les dates d'un journal.

Cette description suit le manuel officiel de GNU tac. Vérifiez tac --help sur votre système, notamment pour les séparateurs personnalisés et les expressions régulières.

Inverser des lignes sans inverser leurs caractères

La syntaxe est tac [OPTION]... [FICHIER...]. Sans fichier, ou avec le nom -, la commande lit l'entrée standard. Le nom tac rappelle cat écrit à l'envers, mais l'opération porte sur les enregistrements, pas sur chaque octet du texte.

printf 'premier\ndeuxieme\ntroisieme\n' | tac

Le résultat est :

troisieme
deuxieme
premier

Aucun fichier n'est créé ni modifié dans cet exemple. Pour appliquer le même traitement à un fichier existant, utilisez tac -- evenements.log. Le séparateur d'options -- protège aussi les noms qui commenceraient par un tiret.

Comprendre le rôle du dernier retour à la ligne

Par défaut, GNU tac rattache le séparateur à la fin de l'enregistrement qui le précède. Si la dernière ligne du fichier ne se termine pas par un retour à la ligne, son inversion peut donc accoler le dernier fragment au fragment suivant dans la sortie. Comparez ces entrées :

printf 'un\ndeux\ntrois\n' | tac
printf 'un\ndeux\ntrois' | tac

Le premier appel produit trois lignes distinctes : trois, deux, puis un. Dans le second, trois n'a pas de séparateur final et la sortie commence par troisdeux sur une même ligne, suivie de un. Ce comportement explique certains résultats surprenants avec des fichiers incomplets ; tac ne répare pas automatiquement leur terminaison.

Traiter plusieurs fichiers dans un ordre connu

Lorsque plusieurs fichiers sont fournis, GNU tac inverse chacun séparément et conserve l'ordre des arguments. Il ne fusionne pas d'abord tous les fichiers pour inverser une chronologie commune. Ce petit laboratoire permet de le voir :

lab=$(mktemp -d "$HOME/tac-lab.XXXXXX") || exit 1
printf 'A1\nA2\n' > "$lab/a.txt"
printf 'B1\nB2\n' > "$lab/b.txt"
tac -- "$lab/a.txt" "$lab/b.txt"

Le résultat attendu est A2, A1, B2, puis B1, une valeur par ligne. Si vous voulez inverser l'ensemble formé par la concaténation des deux fichiers, l'opération est différente :

cat -- "$lab/a.txt" "$lab/b.txt" | tac

Cette fois, vous devez lire B2, B1, A2, puis A1. Même ce résultat n'est pas un tri des dates : il dépend entièrement de l'ordre des fichiers et de leurs lignes.

Choisir un autre séparateur d'enregistrement

Option GNU Rôle
-s CHAINE Remplace le retour à la ligne par cette chaîne comme séparateur.
-b Rattache le séparateur au début de l'enregistrement suivant dans l'entrée.
-r Interprète le séparateur fourni comme une expression régulière.

Pour une chaîne de trois enregistrements terminés par --- :

printf '%s' 'A---B---C---' | tac -s '---'
printf '\n'

Le résultat est C---B---A---. Si le format place au contraire le séparateur avant chaque enregistrement, ajoutez -b :

printf '%s' '---A---B---C' | tac -b -s '---'
printf '\n'

Vous devez alors obtenir ---C---B---A. Le dernier printf des deux blocs ajoute seulement un retour à la ligne pour la lisibilité du terminal. Un séparateur mal choisi peut couper au milieu du contenu utile ; vérifiez d'abord le format et un échantillon. Les règles d'expression régulière de -r doivent être contrôlées dans l'implémentation installée avant d'être utilisées dans un script portable.

Relire un journal depuis la fin et choisir la bonne portée

Pour un journal où chaque événement tient sur une ligne et où les nouvelles entrées sont ajoutées à la fin, l'inversion fait apparaître les dernières lignes en premier. Vous pouvez les parcourir dans la commande less avec tac application.log | less. Un événement réparti sur plusieurs lignes, comme une trace d'erreur, sera lui aussi inversé ligne par ligne ; cette sortie ne conserve donc pas automatiquement les blocs logiques du journal.

Pour contrôler seulement les dix dernières lignes dans l'ordre inverse, combinez tail -n 10 FICHIER | tac. Pour trouver le dernier événement contenant un mot donné dans un fichier fini, la recherche suivante est possible :

printf 'INFO debut\nERREUR ancienne\nINFO suite\nERREUR recente\n' > "$lab/application.log"
tac -- "$lab/application.log" | grep -m 1 'ERREUR'

Le résultat attendu est ERREUR recente. grep -m 1 s'arrête à sa première correspondance ; sur une entrée plus grande, un producteur encore actif peut rencontrer un tube fermé. Examinez les états de pipeline si vous utilisez une politique stricte de traitement des erreurs.

Pour une entrée non repositionnable, GNU tac doit mettre les données en attente, notamment dans un fichier temporaire, avant de pouvoir les relire en sens inverse. Un flux sans fin n'a pas de dernier enregistrement disponible : évitez tail -f FICHIER | tac pour une surveillance en continu. Utilisez le suivi des journaux avec tail pour les nouvelles lignes.

Questions fréquentes

tac et sort -r produisent-ils le même résultat ?

Non. tac renverse l'ordre actuel des enregistrements. sort -r compare leurs valeurs et les trie dans l'ordre inverse selon ses règles.

tac change-t-il le fichier original ?

Non, il écrit le résultat sur sa sortie standard. Si vous ajoutez une redirection, choisissez un autre fichier de sortie : rediriger vers l'entrée peut l'écraser avant la lecture.

Pourquoi aucune sortie n'apparaît-elle avec un flux continu ?

L'ordre inverse dépend de la fin de l'entrée. Si celle-ci ne se termine pas, le lecteur ne peut pas déterminer son dernier enregistrement.

La référence des commandes Linux par tâche regroupe les autres outils de lecture et de traitement de texte.