===== "cat", lire, écrire, concaténer du texte ===== "cat" est une de ces commandes incontournables, elle sert le plus souvent à lire un contenu textuel, mais elle peut faire plus. Son nom est dérivé de l'Anglais "concatenate", "concaténer" en Français. Un signe $ précède les commandes qui ne nécessitent pas de droits administrateur ; un signe # précède celles qui nécessitent des droits administrateur (ces signes ne font PAS partie des commandes). Les lignes qui ne commencent pas par un signe $ ou # correspondent au résultat de la commande précédente.\\ Les touches utilisées sont indiquées entre crochets, exemple **[ctrl]** pour la touche "contrôle" ==== Lire un fichier en console ==== "cat" est adapté à la lecture d'un fichier court, son utilisation de base est très simple :\\ $ cat /home/tux/test.txt blabla, ceci est un test. Nous venons de lire le fichier "test.txt" dans le répertoire personnel de l'utilisateur "tux", rien de difficile. Maintenant nous voulons lire deux fichiers "test.txt" et "test2.txt" qui se trouvent dans le répertoire courant :\\ $ cat test.txt test2.txt blabla, ceci et un test. Et voici un deuxième fichier de test. Ça paraît clair, par défaut "cat" écrit le(s) fichier(s) demandé(s) sur la sortie standard (l'indicateur de la sortie standard, le symbole "**-**", est implicitement supposé si aucune autre sortie n'est indiquée.).\\ "cat" peut appliquer quelques traitements simples au texte, comme par exemple __numéroter toutes les lignes__ (option "**-n**"), ou __seulement les lignes qui contiennent effectivement du texte__ (option "**-b**"). On peut également __supprimer les lignes vides successives__ pour n'en laisser qu'une seule (option "**-s**"), ou __afficher tous les caractères non-imprimables__, tabulations et fins de lignes avec "**-A**".\\ Appliquer ce type de traitements est surtout intéressant lorsqu'on écrit le résultat dans un nouveau fichiers. ==== Écrire et concaténer (réunir) des fichiers ==== "cat" ne sait pas "écrire" à proprement parler, mais pour arriver au même résultat il suffit de rediriger le résultat d'une commande vers un fichier texte :\\ $ cat test.txt blabla, ceci et un test. $ cat test2.txt Et voici un deuxième fichier de test. $ cat -n test.txt test2.txt > test3.txt $ cat test3.txt 1 blabla, ceci et un test. 2 Et voici un deuxième fichier de test. Nous venons de réunir les fichiers "test.txt" et "test2.txt", en ajoutant la numérotation des lignes, dans un fichier "test3.txt".\\ La redirection n'est pas propre à "cat", elle fonctionne de la même façon pour tous les programmes en ligne de commande.\\ ^Symbole de redirection ^Usage ^^^ |**>** //fichier// |Crée le fichier s'il n'existe pas, **remplace** son contenu s'il existe | |**%%>>%%** //fichier// |Crée le fichier s'il n'existe pas, **ajoute** à la fin du fichier s'il existe | :!: Il est essentiel de bien comprendre qu'avec ">" vous remplacez, et donc détruisez, l'ancien contenu du fichier cible si celui-ci existe déjà.\\ Maintenant admettons que l'on veuille écrire du texte dans un nouveau fichier, mais que ce texte n'existe pas encore. Nous allons indiquer à "cat" de prendre en compte le texte tapé jusqu'à un certain signal, et de l'écrire dans un fichier texte :\\ $ cat << FIN >> test4.txt >Je veux écrire du texte dans un fichier >Ça je voudrais bien \ >que ça tienne sur une ligne. > >Simple ! >FIN Attention, il y a un piège, le signe ">" en début de chaque ligne qui suit la commande indique simplement une invite de commande, c'est un symbole qui indique que "cat" "attend" que vous écriviez quelque chose. Ce signe ">" n'est pas à taper, et il n'apparaît pas dans le résultat.\\ Bon, et ça donne quoi ?\\ $ cat test4.txt Je veux écrire du texte dans un fichier Ça je voudrais bien que ça tienne sur une ligne. Simple ! Quelques explications, le texte est rendu tel quel, chaque appui sur la touche [entrée] entraîne un saut de ligne, sauf si la ligne se termine par un antislash "**\**". Si la ligne est laissée vide cela donne une ligne vide.\\ Le mot "FIN" n'est pas écrit dans le fichier, c'est notre marqueur de fin de fichier défini dans la commande. On peut utiliser n'importe quel mot comme marqueur, par convention on trouvera souvent "%%EOF%%" qui signifie "End Of File" ("fin de fichier" en Anglais).\\ Trop facile "cat" ? Amusons nous un peu alors ! Que ce passe-t-il avec du texte un peu "spécial", comme des commandes, des variables ou des caractères spéciaux ?\\ $ cat <<- EOF >Ceci est un test >si on met une commande ça fait quoi ? >who >et comme ça ? >`who` >Hoo, et alors avec ça ? >$(uname -r) >"$(uname -r)" >Mais je veux juste l'écrire, pas l'exécuter ! >\$(uname -r) >C'est mieux, quel bazar. >* $ ^ >Tiens, ça ne fait rien avec les caractères spéciaux... >Bon, ça suffit pour le moment. >EOF Nous avons changé la commande, ici nous redirigeons le texte simplement vers la sortie standard, soit la console, avec le symbole "**-**". Nous avons choisi "%%EOF%%" comme marqueur de fin de fichier. Le résultat :\\ Ceci est un test si on met une commande ça fait quoi ? who et comme ça ? tux :0 2009-06-17 07:23 Hoo, et alors avec ça ? 2.6.29.5-vanilla64 "2.6.29.5-vanilla64" Mais je veux juste l'écrire, pas l'exécuter ! $(uname -r) C'est mieux, quel bazar. * $ ^ Tiens, ça ne fait rien avec les caractères spéciaux... Bon, ça suffit pour le moment. On voit qu'il faut prendre quelques précautions, les commandes gardent leur valeur littérale, sauf si on indique au shell de les évaluer avec des "backticks" "**`**" (cas du deuxième "who"). Pour les variables c'est plus compliqué, elles sont évaluées même si elles sont encadrées par des guillemets simples ou doubles (qui gardent leur valeur littérale ici). Pour préserver la valeur littérale d'une variable il faut donc l'échapper avec un antislash "**\**", par exemple "\$PATH" pour écrire "$PATH" et non obtenir la valeur de la variable.\\ Mmm, il n'y a pas plus simple pour taper du texte et préserver les variables ? Si, il suffit d'utiliser "cat" de cette manière :\\ $ cat > test.txt Je tape mon texte. Cette fois les variables \ seront préservées. $PATH Les commandes aussi `who` $(uname -r) Pour terminer la séquence utilisez les touches [ctrl] [d], cette fois-ci les lignes ne commencent pas par le signe ">", il ne s'agit plus d'invites de commandes. Tout le texte garde sa valeur littérale. Le résultat :\\ $ cat test.txt Je tape mon texte. Cette fois les variables \ seront préservées. $PATH Les commandes aussi `who` $(uname -r) Tout est préservé. ==== "cat" est-il vraiment utile ? ==== Oui ! (Ouf), mais finalement pas si souvent. Voici les cas typiques où l'emploi de "cat" est une mauvaise idée :\\ * Lire un long fichier de journal (log), on utilisera plutôt un pager comme "less" ou "most" qui rend la lecture plus confortable, ou "head"/"tail" pour ne lire que le début/la fin du fichier.\\ * Redirection vers "[[commande:grep_egrep:|grep]]" pour chercher une expression. C'est une lourdeur inutile, on peut utiliser "grep" directement sur des fichiers textes, pas besoin de passer par "cat" et une redirection.\\ * Pour des fichier binaires, "cat" ne vous renseignera pas beaucoup, pour rechercher du texte "compréhensible" dans une archive binaire il faut utiliser "strings" par exemple.\\ En revanche "cat" peut être utile là où ne l'attend pas, par exemple pour mettre bout-à-bout deux archives vidéo ou images ".iso". Pour que cela fonctionne il faut que les vidéos aient les mêmes propriétés (format, débit, encodage ...), et que les vidéos ou les images ".iso" aient été au préalable coupées volontairement. Un exemple avec une image ".iso"\\ $ split --bytes=50M pmagic-4.2.iso $ ls pmagic-4.2.iso xaa xab $ cat xaa xab > pmagic-4.2_2.iso $ md5sum pmagic-4.2.iso 8a1ad4e84cae8fe1d1e230cdc8ec1bd2 pmagic-4.2.iso $ md5sum pmagic-4.2_2.iso 8a1ad4e84cae8fe1d1e230cdc8ec1bd2 pmagic-4.2_2.iso Nous avons une image ".iso" de 95Mo, nous la coupons en deux avec la commande "split", en précisant une taille maximale pour les parties de 50Mo (option "**%%--bytes=%%**"). Cela revient à produire deux fichiers "xaa" et "xab" (ce type de noms est le défaut de la commande "split", voir "[[commande:commande-manuel:|man]] split").\\ Avec "cat" nous réunissons à nouveau ces deux parties en une image ".iso", nous changeons le nom de l'image pour ne pas écraser l'originale qui se trouve dans le même répertoire.\\ Pour vérifier que l'opération n'a pas altérée l'image nous exécutons une somme de contrôle "md5" sur l'image originale, et celle produite par "split" puis "cat" : ce sont bien les mêmes.\\ La même opération fonctionne parfaitement avec une vidéo, on peut la découper en nombreux petits morceaux avec "split", et la reconstituer avec "cat".\\ $ split --bytes=1M lion.ogv $ ls lion.ogv xaa xab xac xad $ cat xaa xab xac xad > lion2.ogv La video résultante "lion2.ogv" est exactement la même que l'originale "lion.ogv", le lecteur video "VLC" la lira aussi bien.\\ Pratique pour envoyer de gros fichiers.\\ ==== Vous préférez les chiens aux les chats ? ==== "cat" en Anglais signifie "chat", alors quand un développeur a l'idée de créer une version "améliorée" de "cat" il la nomme naturellement "dog" ("chien" en Anglais)... "dog" est présent dans les dépôts de quelques distributions, dont [[debian:|Debian]]. Si vous êtes curieux vous irez faire un tour dans son manuel pour voir les différences avec "cat". "dog" n'étant pas une commande standardisée elle est d'un usage anecdotique, et sera à éviter absolument dans des scripts par exemple (pour des raisons de portabilité). "dog" possède de nombreuses options supplémentaires, peut travailler sur des url. Un extrait du manuel pour le plaisir de la rubrique "NAME" :\\ DOG(1) User Manuals DOG(1) NAME dog - better than cat SYNOPSIS dog [-AbBeEnstTuv] [-w[cols]] [-l lines] [--show-all] [--number-nonblank] [--no-blanks] [--bind=port] [--dos] [--show-ends] [--hang-up] [--images] [--links] [--lower] [--mac] [--number] [--no-header] [--squeeze-blank] [--sock=domain:port] [--sock-test] [--show-tabs] [--raw] [--rot=num] [--udp] [--unix] [--upper] [--show-non‐ printing] [--hide-nonprinting] [--help] [--hex] [--skip-tags] [--version] file | URL | - ... DESCRIPTION dog writes the contents of each given file, URL, or the standard input if none are given or when a file named ’-’ is given, to the standard output. It currently supports the file, http, and raw URL types. It is designed as a compatible, but enhanced, replacement of cat(1). [...] Amusez vous bien ! ;-) ------------------------------------------------------------------------------------- ==================================================================== [[http://www.linuxpedia.fr/forum/index.php?action=pm;sa=send;u=15|Envoyer un message au mainteneur]] ==================================================================== [[commande:commande:|Retour au sommaire "La ligne de commande"]]