arthur.bebou

Le site arthur.bebou.netlib.re - retour accueil

git clone git://bebou.netlib.re/arthur.bebou

Log | Files | Refs |

commit a73e02fcc431b9aee7f78337841740e2272e28cb
parent db03c5a6ca782c6b3c854b98c97f58ca92f9d85d
Auteurice: Arthur Pons <arthur.pons@unistra.fr>
Date:   Thu, 15 May 2025 20:19:03 +0200

Relecture de l'article avoid software

Diffstat:
Mcontents/avoid-software-commentaires/index.sh | 255++++++++++++++++++++++++++++++++++++++-----------------------------------------
1 file changed, 123 insertions(+), 132 deletions(-)

diff --git a/contents/avoid-software-commentaires/index.sh b/contents/avoid-software-commentaires/index.sh @@ -6,8 +6,6 @@ publication: 2025-05-14 section: main -Article non relu et **pas fini**. - La plupart des informations intéressantes de cet article sont directement tirées de [cet article](https://dwheeler.com/essays/filenames-in-shell.html) vraiment détaillé. Merci à David A. Wheller qui se trouve avoir le même nom que [le @@ -33,33 +31,33 @@ Cet article a pour but d'être une contribution à ce fanzine : * en proposant une partie expliquant comment transformer les commandes en scripts qui peuvent prendre des arguments -## Les limites fréquemment rencontrés +## Les limites fréquemment rencontrées Les scripts de ce zine contiennent des limites récurrentes, à savoir : - * La mauvaise gestion des fichiers commençant par `-` + * La mauvaise gestion des fichiers commençant par un tiret `-` * La mauvaise gestion des fichiers contenant des espaces * La mauvaise gestion des cas où aucun fichier ne correspond au critère de recherche * Ne pas être "portable", c'est-à-dire ne pas pouvoir fonctionner sur un large - ensemble de shell et de systèmes d'exploitation + ensemble de shells et de systèmes d'exploitation -Avant de rentrer dans les détails de ces limites il faut ête clair. Tous les +Avant de rentrer dans les détails de ces limites il faut être clair. Tous les logiciels, et en particulier les scripts de ce zine, n'ont pas vocation à être parfaitement corrects. Leur usage est généralement situé, sur un OS particulier pour une personne particulière dans un dossier particulier. Dans la plupart des -contextes les limites de ces scripts ne sont pas pertinentes. Il n'importe pas +contextes les limites de ces scripts ne sont pas gênants. Il n'importe pas qu'un script ne gère pas les fichiers dont les noms comportent des espaces si -l'on *sait* qu'on l'utilise sur des fichiers dont les noms ne comportent *pas* -d'espace. Cela dit puisque ce zine est publique et puisque j'aime apprendre des -choses sur le shell je pense qu'il est opportun d'en chercher et partager des -alternatives plus robustes. +l'on *sait* qu'on l'utilise sur des fichiers dont les noms ne comportent pas +d'espace. Cela dit puisque ce zine est public et puisque j'aime apprendre des +choses sur le shell je pense qu'il est opportun de partager des alternatives +plus robustes. -### La mauvaise gestion des fichiers commençant par `-` +### La mauvaise gestion des fichiers commençant par un tiret `-` -Imaginons que nous voulons lancer une commande sur plusieurs fichiers d'un -dossier à la fois.Par exemple, lister tous les jpeg. Pour cela on peut utiliser -les "globs" : +Imaginons que nous voulions lancer une commande sur plusieurs fichiers d'un +dossier à la fois. Par exemple, lister tous les jpeg. Pour cela on peut +utiliser les "globs" (ou "Pattern Shells") : $ ls *.jpeg machin.jpeg @@ -67,18 +65,18 @@ les "globs" : Dans les globs le caractère `*` veut dire "n'importe quel caractère autant de fois que nécessaire". Donc `*.jpeg` veut dire "tous les fichiers se terminant -par `.jpeg` et, pour peu que les fichiers soient correctement nommés, adresser -tous les jpeg d'un dossier. On peut penser les globs comme des expressions -régulières beaucoup moins puissantes. +par `.jpeg`. On peut penser les globs comme des expressions régulières beaucoup +moins puissantes. -D'autres caractères des globs intéressants : +D'autres caractères significatifs des globs : * `?` : "n'importe quel caractère une fois" * `[]` : introduit ce que l'on appelle une "classe de caractère". En écrivant `[abc]` on dit "une fois le caractère a, b ou c". Il est également possible - d'utiliser le caractère `-` pour décrire une étendue de caractère. `[3-8]` - ou `[d-h]` voudront dire "une fois un entier entre 3 et 8 inclus" et "une - fois une lettre minuscule entre d et h dans l'ordre alphabétique inclus". + d'utiliser le caractère `-` à l'intérieur d'une classe de caractère pour + décrire une étendue de caractère. `[3-8]` ou `[d-h]` voudront dire "une + fois un entier entre 3 et 8 inclus" et "une fois une lettre minuscule entre + d et h inclus dans l'ordre alphabétique". * `!` : dans une classe de caractère permet de prendre le complément des caractères. `[!abc]` veut dire "une fois n'importe quel caractère *sauf* a, b ou c". @@ -88,7 +86,7 @@ précises et alambiquées comme : $ ls *-[!1][0-9][0-9]-??.jpeg -convertir tous les fichiers commençant n'importe comment, suivi d'un tiret, +lister tous les fichiers commençant n'importe comment, suivi d'un tiret, suivi de n'importe quel caractère n'étant pas un `1` suivi de deux entiers suivi d'un tiret suivi d'exactement deux caractères suivi de `.jpeg`. @@ -102,12 +100,12 @@ va s'étendre en ls "a.jpg" "b.jpg" -avant de s'éxecuter. Il est possible dans certains shell à l'écriture de la -commande d'obtenir un retour des fichiers qui correspondent en appuyant sur la +avant de s'éxecuter. Il est possible dans certains shells, à l'écriture de la +commande, d'obtenir un retour des fichiers qui correspondent en appuyant sur la touche tabulation comme si l'on voulait compléter le glob. Avec ma configuration de `zsh` le développement se fait carrément en direct dans le prompt. -Si vous êtes particulièrement alerte ce fonctionnement par réécriture de +Si vous êtes particulièrement alertes ce fonctionnement par réécriture de commande devrait vous donner envie de tester un truc. Que se passe-t-il si un le nom d'un fichier commence par `-` ? Admettons qu'il existe un fichier nommé `-azerty.jpg` et que l'on utilise le glob `*.jpg` en argument de la fonction @@ -115,13 +113,11 @@ le nom d'un fichier commence par `-` ? Admettons qu'il existe un fichier nommé $ ls *.jpg # devient - $ ls -azerty.jpg + $ ls "-azerty.jpg" ls : option invalide -- 'z' On se retrouve avec une erreur. Et pour cause, la commande a cru que -`-azerty.jpg` est la déclaration d'options de la commande `ls`. C'est d'autant -plus facile de tomber sur cette erreur que le tiret `-` arrive avant la plupart -des autres caractères dans l'ordre alphanumérique. +`-azerty.jpg` était la déclaration d'options de la commande `ls`. Il y a deux manières de se prémunir de cette erreur. La manière la plus universelle est d'ajouter `./` devant le glob. `./` voulant dire "le dossier @@ -140,13 +136,13 @@ commande : $ ls -larth -- -azerty.jpg -rw-r--r-- 1 arthur arthur 0 10 mai 11:27 -azerty.jpg -Ici `--` permet à la commande de savoir que tout ce qu'il suit doit être -interpréter comme des arguments et non pas comme de potentielles options. Bien +Ici `--` permet à la commande de savoir que tout ce qui suit doit être +interprété comme des arguments et non pas comme de potentielles options. Bien que [cette syntaxe soit POSIX](https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap12.html#tag_12_02) -toutes les commandes ne respectent pas ce principe, en particulier les commandes -qui ne sont pas "de base" sur les systèmes Unix. La première solution est donc -préférable. +toutes les commandes ne respectent pas ce principe, en particulier les +commandes qui ne sont pas "de base" sur les systèmes Unix. La première solution +est donc préférable. ### La mauvaise gestion des fichiers dont le nom contient des espaces @@ -154,7 +150,7 @@ Dans les systèmes UNIX supportant UTF-8 les noms des fichiers peuvent contenir tous les caractères sauf le caractère nul (`\0`). Écrire des scripts qui gèrent correctement les fichiers en toutes circonstances nécessite de faire attention à la manière dont le shell interprète les blancs (espace, tabulation, retour à -la ligne etc). Les blancs, dans la pratique presque toujours les espaces, +la ligne etc). Les blancs, dans la pratique presque toujours des espaces, servent au shell à distinguer les éléments les un des autres. C'est la raison pour laquelle il est important de toujours mettre un ou plusieurs espaces entre les noms des commandes et leurs options et arguments : @@ -164,15 +160,14 @@ les noms des commandes et leurs options et arguments : Comme on le voit dans la commande ci-dessus il peut y avoir des exceptions. Les options peuvent être combinées (`-la`). Lorsque les options peuvent prendre des arguments on peut généralement coller les deux puisqu'il n'y a pas d'ambiguité -sur la découpe comme l'option `-i` qui est nécessairement suivi d'un suffixe, -espace ou pas : +sur la découpe. Par exemple l'option `-i` de `sed` qui est nécessairement suivi +d'un suffixe, espace ou pas : $ sed -i.bak 's/machin/truc/' *.txt -Si les espaces sont si importants on peut se demander quel est leur impact sur -la manière de comprendre les arguments quand ils sont des chemins de fichiers. -Imaginons que l'on a deux pdf `fichier.pdf` et `fichier 2.pdf`. Si l'on veut -afficher des informations à leur propos on risque de tomber sur une erreur : +Imaginons maitenant que l'on a deux pdf `fichier.pdf` et `fichier 2.pdf`. Si +l'on veut afficher des informations à leurs propos on risque de tomber sur une +erreur : $ ls -la fichier.pdf fichier 2.pdf ls: impossible d'accéder à 'fichier': Aucun fichier ou dossier de ce type @@ -186,9 +181,11 @@ que cet espace ne démarque pas la frontière entre deux éléments différents faut ajouter un autre marqueur. L'objectif est de faire en sorte que l'espace soit compris littéralement. Il y a deux manière de le faire : - * Englober le chemin entre deux guillemets `"` ou apostrophes `'` : "fichier - 2.pdf" - * Echapper l'espace avec un `\` : fichier\ 2.pdf + * Englober le chemin entre deux guillemets `"` ou apostrophes `'` : `"fichier + 2.pdf"` + * Echapper l'espace avec un `\` : `fichier\ 2.pdf` + +Employer l'une ou l'autre permet de découper les arguments correctement : $ ls -la fichier.pdf "fichier 2.pdf" -rw-r--r-- 1 arthur arthur 365368 9 avril 15:00 fichier.pdf @@ -207,7 +204,7 @@ zsh pré-echappe les espaces et affichera les résultats : On remarque ici que le glob est immunisé à la malédiction des espaces dans les noms de fichier. Ce n'est pas par hasard que dans le titre précédent j'ai remplacé `ls ?.jpg` par `ls "a.jpg" "b.jpg"`. La raison pour laquelle les globs -ne rencontrent pas de problème est parce qu'ils sont interprétés *après* le +ne rencontrent pas ce problème est parce qu'ils sont interprétés *après* le découpage des éléments par le shell. Le shell découpe `ls fichier*` en deux éléments. Il détecte que le second est un glob qu'il développe en `fichier.pdf` et `fichier 1.pdf`. A ce stade le shell a déjà découpé les éléments de la @@ -218,26 +215,26 @@ bons arguments. Alors si les globs sont immunisé et si l'on fait rarement l'erreur d'écrire à la main des chemins contenant des espaces, quand est-ce que cela pose problèmes ? Lorsque l'on dépasse la "simple" commande et que l'on se met à utiliser des -variable ou à combiner des sorties de commandes avec d'autres éléments de -syntaxe. +variables ou à combiner des sorties de commandes avec d'autres éléments de +syntaxe. Dès que l'on script un peu quoi. Imaginons vouloir mettre la valeur `fichier 1.pdf` dans une variable : $ file=fichier 1.pdf sh: 1: 1.pdf: not found $ echo $file +   - - -Le shell a découpé cette commande en deux partie : la déclaration de la variable -`file` et la tentative d'exécution de la commande inexistante `1.pdf`. Plutôt -cohérent avec ce que l'on a appris jusque là. Ce qui est peut-être plus +Le shell a découpé cette commande en deux parties : la déclaration de la +variable `file` et la tentative d'exécution de la commande inexistante `1.pdf`. +Plutôt cohérent avec ce que l'on a appris jusque là. Ce qui est peut-être plus surprenant c'est que la variable "$file" est vide. Et pour cause la syntaxe `var=valeur cmd` est particulière. Elle ne déclare la variable `var` que pour l'exécution de la commande `cmd`. Elle n'existera plus directement après. Cette -syntaxe n'est donc pas à confondre avec `var=valeur;cmd` qui fera les deux -opération successivement et ainsi aura durablement créé la variable `var` pour -la suite. Bref c'était pas le propos. +syntaxe est utilisée pour configurer des variables d'environnement pour des +commandes qui en ont besoin. Elle n'est donc pas à confondre avec +`var=valeur;cmd` qui fera les deux opérations successivement. Bref c'était pas +le propos. On peut corriger notre affaire très simplement en faisant `file="fichier 1.pdf"`. Maintenant on veut utiliser la variable plus tard dans le script : @@ -247,11 +244,11 @@ On peut corriger notre affaire très simplement en faisant `file="fichier ls: impossible d'accéder à 'fichier': Aucun fichier ou dossier de ce type ls: impossible d'accéder à '1.pdf': Aucun fichier ou dossier de ce type -On retombe sur notre souci de découpage ! C'est parce que contrairement au -développement des globs le développement des variables se fait *avant* le -découpage des commandes. `ls $file` devient alors `ls fichier 1.pdf` et la -commande `ls` sera donc exécutée avec deux arguments séparés. Pour y remédier il -faut préemptivement protéger la variable avec des guillemets - et non pas des +On retombe sur notre souci de découpage ! Contrairement au développement des +globs le développement des variables se fait *avant* le découpage des +commandes. `ls $file` devient alors `ls fichier 1.pdf` et la commande `ls` sera +donc exécutée avec deux arguments séparés. Pour y remédier il faut +préemptivement protéger la variable avec des guillemets - et non pas des apostrophes qui ont pour comportement de ne pas étendre les variables à l'intérieur mais de considérer tout littéralement : @@ -272,10 +269,10 @@ Les globs que l'on a vu précédemment ne permettent pas, dans POSIX du moins, d faire des recherches récursives. `./*.pdf` ne correspondra qu'aux fichiers du *dossier courant* terminant par `.pdf`. Si l'on veut descendre dans les sous-répertoires *et* avoir tout un tas d'autres filtres à notre disposition - -tel que la taille du fichier, sa date de dernière modification etc - il faut +la taille du fichier, sa date de dernière modification etc - il faut avoir recours à `find`. `find` renvoie une liste des fichiers correspondant aux filtres qu'on lui a indiqué. En admettant que l'on a un dossier dans lequel un -fichier `fichier 2.pdf se trouve` : +fichier `fichier 2.pdf` se trouve : $ find -name '*.pdf' ./fichier.pdf @@ -296,7 +293,7 @@ boucle `for` pour effectuer une opération sur chacun de ces fichiers : Mais patatra, *encore* notre souci de découpage. Le développement de la capture de commande `$(find -name '*.pdf')` se fait avant le découpage. On a donc en -réalité exécuter : +réalité exécuté : $ for file in ./fichier.pdf ./dossier/fichier 2.pdf ./fichier 1.pdf;do ... @@ -310,29 +307,30 @@ avec l'option `-0` d'`xargs`. Cela permettra à `find` de délimiter les différents fichiers trouvés par le caractère nul et à `xargs` de délimiter les arguments sur ce même caractère nul. Cela résout notre problème puisque le seul caractère qui ne peut *pas* être dans le nom d'un fichier est justement le -caractère NUL[^2]. Depuis 2023 POSIX inclus les options nécessaires dans `find` -et `xargs` permettant de le faire. Si l'on ne peut pas garantir que ce soit -implémenté partout du fait que la spécification est récente - et parce que tout -les outils UNIX ne font pas d'énormes efforts pour respecter POSIX - c'est tout -de même la solution que je privilégie. +caractère nul[^2]. Depuis 2023 POSIX inclus les options nécessaires dans `find` +et `xargs` permettant de le faire. Si l'on ne peut pas garantir que tous les +`find` et `xargs` du monde l'implémentent du fait que la spécification est +récente c'est tout de même la solution que je privilégie. L'idée générale est de trouver les fichiers que l'on veut, par exemple tous les fichiers terminant par `.pdf` (`find -type f -name '*.pdf'`) et de les passer à -`xargs` pour lancer une commande avec ces fichiers pour arguments : +`xargs` pour lancer une commande avec ces fichiers en arguments : $ find -type f -name '*.pdf' -print0 | xargs -0 ls -la -rw-r--r-- 1 arthur arthur 0 15 mai 10:27 './dossier/fichier 2.pdf' -rw-r--r-- 1 arthur arthur 0 15 mai 10:27 './fichier 1.pdf' -rw-r--r-- 1 arthur arthur 0 15 mai 10:27 ./fichier.pdf -On constate qu'il n'y a bien qu'aucun `ls` n'a été tenté sur un fichier -n'existant pas. Le découpage a été fait correctement. La commande `xargs` est -assez complexe et je ne vais pas plus en parler ici. A noter que dans sa version -GNU `xargs` va tout de même exécuter une fois la commande si aucun argument ne -lui a été fourni en entrée standard. Je *crois* que ce comportement n'est pas -POSIX. Pour reproduire le comportement plus intuitif d'aucune exécution si -`find` ne trouve aucun fichier il faut lui ajouter l'option `-r`. La version BSD -ne souffre pas du même problème. Pour le reste de cet article j'omet le `-r`. +On constate qu'aucun `ls` n'a été tenté sur un fichier n'existant pas. Le +découpage a été fait correctement. La commande `xargs` est assez complexe et je +ne vais pas plus en parler ici. Des exemples seront donnés dans les +alternatives aux différentes commandes du zine par la suite. À noter que dans +sa version GNU `xargs` va tout de même exécuter une fois la commande si aucun +argument ne lui a été fourni en entrée standard. Je *crois* que ce comportement +n'est pas POSIX. Pour reproduire le comportement plus intuitif d'aucune +exécution si `find` ne trouve aucun fichier il faut lui ajouter l'option `-r`. +La version BSD ne souffre pas du même problème. Pour le reste de cet article +j'omet le `-r`. ### Mauvaise gestion des cas où aucun fichier ne correspond au critère de recherche @@ -346,9 +344,9 @@ mais ne trouve aucun fichier correspondant le glob lui même sera renvoyé : machin.truc C'est inoffensif pour un `ls` mais cela pourrait mener à l'exécution de -commandes que l'on ne souhaite pas. Lorsqu'on utilise les globs pour amorcer une -boucle comme vu précédemment la solution est de vérifier à chaque fois si le -fichier sur lequel on tente de lancer la commande existe bel et bien[^4] : +commandes que l'on ne souhaite pas. Lorsqu'on utilise les globs pour amorcer +une boucle la solution est de vérifier à chaque fois si le fichier sur lequel +on tente de lancer la commande existe bel et bien[^4] : for file in ./*.pdf;do if [ -e "$file" ];then @@ -379,7 +377,7 @@ l'existence du fichier à chaque itération de la boucle. Le monde du shell est, encore en 2025, très morcelé. On a l'impression que toutes les personnes faisant du shell partagent plus ou moins le même -environnement technique mais c'est lion d'être le cas. Le shell par défaut sur +environnement technique mais c'est loin d'être le cas. Le shell par défaut sur les linux est traditionnellement `bash`. Sur MacOS c'est `zsh` depuis quelques temps. Sur OpenBSD c'est `ksh`. Les scripts sont souvent écrits pour fonctionner avec `/bin/sh` qui est généralement un lien symbolique vers un autre shell - par @@ -388,14 +386,14 @@ script shell s'exécute correctement sur la plupart des machines. A ce sujet voi [le portage de catium vers OpenBSD et MacOS](/portabilite/) ou [le portage de catium vers debian 1.3](/catium-archeo/). -Puisque ce zine est sur le web, qu'il s'adresse à une communauté ayant une +Puisque ce zine est sur le web et qu'il s'adresse à une communauté ayant une diversité de machine assez grande je pense qu'il est utile de proposer des alternatives portables de chaque commande. Il n'y a pas une seule technique magique permettant d'assurer la portabilité d'un script. L'idéal reste de le tester sur les systèmes sur lesquels on veut qu'il fonctionne. Cela dit l'outil [shellcheck](https://www.shellcheck.net/) détecte tout un tas -de soucis dans les scripts shell dont [problèmes de +de soucis dans les scripts shell dont des [problèmes de portabilité](https://github.com/koalaman/shellcheck?tab=readme-ov-file#portability). De plus il existe un standard mi-descriptif mi-prescriptif nommé POSIX qui spécifie, entre autre, le fonctionnement des [commandes traditionnelles du monde @@ -404,15 +402,15 @@ l'ensemble se limiter à ces commandes et aux options spécifiées dans ce stand est un bon moyen d'augmenter les chances qu'un script soit portable. Le shell depuis lequel je teste mes scripts est `dash`. Il est, en théorie, fait pour être conforme au standard POSIX mais dans la pratique ce n'est pas tout à fait -le cas. Qu'un script fonctionne sous `dash` ne garantit donc pas que sa syntaxe -soit strictement POSIX. +le cas. Le fait qu'un script fonctionne sous `dash` ne garantit donc pas que sa +syntaxe soit strictement POSIX. Dans l'ensemble les règles de base vont être : * Utiliser le shebang `#!/bin/sh` en début de script * Ne pas utiliser d'option non POSIX * Ne pas utiliser de commande non POSIX autre que celles clairement déclarées - en dépendances. + en dépendance * Vérifier que le script est correctement exécuté par `dash` * Vérifier que `shellcheck` ne renvoit aucune erreur @@ -421,18 +419,19 @@ Dans l'ensemble les règles de base vont être : J'aurais tendance à dire qu'étant donné la manière dont ils sont présentés, ce qui constitue cette partie sont plutôt des *commandes* que des *scripts*. -Habituellement les *scripts* vont être une ou plusieurs commandes inscrites dans -un fichier que l'on éxecute comme une seule commande par la suite. C'est du -détail mais si une section au sujet de la "scriptisation" des commandes devait -être ajoutée ça rendrait les choses plus claires. +Habituellement les *scripts* vont être une ou plusieurs commandes inscrites +dans un fichier que l'on éxecute comme une seule commande par la suite. C'est +du détail mais si une section au sujet de la "scriptisation" des commandes +devait être ajoutée ça rendrait les choses plus claires. Je propose une ébauche +[ici](/avoid-software-commentaires/#faire-des-scripts-et-en-faire-une-commande). ### Convertir des formats d'image La version du zine : - * ne gère pas correctement les fichiers commençant par un `-` + * ne gère pas correctement les fichiers commençant par un tiret `-` -Des alternatives plus robustes de cette commande sont, dans l'ordre de +Deux alternatives plus robustes de cette commande sont, dans l'ordre de préférence : mogrify -format formatfinal ./*.formatàconvertir @@ -453,11 +452,11 @@ RAS La version du zine : - * ne gère pas correctement les fichiers commençant par un `-` + * ne gère pas correctement les fichiers commençant par un tiret `-` * ne gère pas correctement l'absence de fichier correspondant au critère de recherche -Une version plus robuste et portable serait donc : +Une version plus robuste et portable serait : for img in ./*.jpg; do if [ -e "$img" ];then @@ -474,7 +473,7 @@ Une version récursive pourrait être : La version du zine : - * ne gère pas correctement les fichiers commençant par un `-` + * ne gère pas correctement les fichiers commençant par un tiret `-` * ne gère pas correctement l'absence de fichier correspondant au critère de recherche @@ -503,7 +502,7 @@ RAS La version du zine : - * ne gère pas correctement les fichiers commençant par un `-` + * ne gère pas correctement les fichiers commençant par un tiret `-` * ne gère pas correctement l'absence de fichier correspondant au critère de recherche @@ -535,19 +534,20 @@ Au passage petite explication du renommage. Il se fait avec la syntaxe syntaxes similaires pour retirer le plus grand suffixe possible et les préfixes les plus petits et grands. -`${f%.m4a}.mp3` est donc un moyen de prendre une variable `$f` dans laquelle on a -par exemple `truc.m4a`, lui retirer sno extension pour avoir `truc` et y ajouter -une nouvelle extension `.mp3` pour obtenir `truc.mp3` en fin de course. +`${f%.m4a}.mp3` est donc un moyen de prendre une variable `$f` dans laquelle on +a, par exemple, `truc.m4a`, lui retirer son extension pour avoir `truc` et y +ajouter une nouvelle extension `.mp3` pour obtenir `truc.mp3`. ### Exporter chaque glyphe d’une fonte en fichier svg -C'est du python. +C'est du python. Je regarderai peut-être si c'est possible sans. En attendant +je passe. ### Supprimer les espaces dans les noms de fichier La version du zine : - * ne gère pas correctement les fichiers commençant par un `-` + * ne gère pas correctement les fichiers commençant par un tiret `-` * ne gère pas correctement l'absence de fichier correspondant au critère de recherche * n'est pas portable @@ -559,14 +559,12 @@ Une version plus robuste et portable serait donc : done La *capture de commande* introduite avec `$()` permet d'exécuter une commande -dans notre commande. Elle sera évaluée d'abord. En l'occurence elle émet le -contenu de `$f` dans la commande `tr ' ' '_'` qui va convertir tous les espaces -par des `_`. Ainsi une fois la capture de commande évaluée la commande que l'on -exécute vraiment ressemblera à : +dans notre commande. Elle sera évaluée avant la commande générale. En +l'occurence elle émet le contenu de `$f` dans la commande `tr ' ' '_'` qui va +convertir tous les espaces par des `_`. Ainsi, une fois la capture de commande +évaluée, la commande que l'on exécute vraiment ressemblera à : - for f in ./*\ *;do - [ -e "./test truc" ] && mv "./test truc" "./test_truc" - done + [ -e "./test truc" ] && mv "./test truc" "./test_truc" C'est pas terriblement performant parce qu'il faut, pour chaque fichier ou dossier, exécuter une sous commande pour avoir une version sans les espaces. @@ -577,23 +575,21 @@ Une version récursive pourrait être : find . -name '* *' -print0 | xargs -0 -n1 sh -c 'mv "$1" "$(echo "$1" | tr " " "_")"' -- -Si l'on accepte une dépendance on peut utiliser le très bon `rename`, -installable sur debian en faisant `apt install rename`. Il permet de renommer -des fichiers via l'utilisation de commandes perl, qu'on peut, ici seulement et -pour faire simple, considérer comme des commandes `sed`. Notre besoin est donc -satisfait avec : +Si l'on accepte une dépendance on peut utiliser le très bon `rename`. Il permet +de renommer des fichiers via l'utilisation de commandes perl, qu'on peut, ici +seulement et pour faire simple, considérer comme des commandes `sed`. Notre +besoin est donc satisfait avec : $ rename 'y/ /_/' ./* C'est super rapide et propre. En mode interactif je recommande l'utilisation de -`rename`. Dans des scripts je recommande la version précédente ou l'une qui -suivra dans la partie au sujet de `find` plus tard. +`rename`. Dans des scripts je recommande l'une des versions précédentes. ### Renommer des fichiers par lot La version du zine : - * ne gère pas correctement les fichiers commençant par un `-` + * ne gère pas correctement les fichiers commençant par un tiret `-` * ne gère pas correctement l'absence de fichier correspondant au critère de recherche * n'est pas portable @@ -610,9 +606,8 @@ Les raisons d'utiliser `printf` plutôt qu'`echo` sont nombreuses et documentée [ici](https://unix.stackexchange.com/questions/65803/why-is-printf-better-than-echo) par Stéphane Chazelas. `let` et l'option `-v` de `mv` ne sont pas POSIX. -Une version récursive pourrait être : - - Reste à trouver +Je ne propose pas de version récursive parce que ça ne fait pas bien sens et +risquerait d'être un peu trop dangereux. ### Compresser un PDF @@ -622,11 +617,11 @@ RAS La version du zine : - * ne gère pas correctement les fichiers commençant par un `-` + * ne gère pas correctement les fichiers commençant par un tiret `-` * ne gère pas correctment les espaces dans les noms des fichiers * n'est pas portable -Une version plus robuste et portable serait donc : +Une version plus robuste et portable serait : #! /bin/sh @@ -655,14 +650,10 @@ Une version plus robuste et portable serait donc : done L'option POSIX `-p` de `mkdir` permet à `mkdir` de créer un chemin complet -`truc/machin/bidule` sns avoir à créer chaque dossier et sous-dossier un à un. +`truc/machin/bidule` sans avoir à créer chaque dossier et sous-dossier un à un. Aussi elle permet à `mkdir` de ne pas renvoyer d'erreur si le dossier existe déjà. Dans de nombreux cas le comportement induit par `-p` est celui souhaité. -Une version récursive pourrait être : - - Reste à trouver - ## Travailler avec des fichiers cachés Si l'on a des fichiers cachés les globs type `./*.pdf` ne vont pas fonctionner. @@ -683,11 +674,11 @@ Pour inclure les fichiers cachés il faut ajouter d'autres globs : ./fichier_pas_secret ./.fichier_secret -## Faire des scripts et en faire une commande +## Faire de ces scripts des commande à part entière -Chaque commande que l'on a vu jusque là est reproductible et appelable depuis -n'importe où dans votre système sous forme de script. Pour créer un script nommé -`rmspace` depuis une commande il faut : +Chaque commande que l'on a vu jusque là peut être rendue reproductible et +appelable depuis n'importe où dans votre système sous forme de script. Pour +créer un script nommé `rmspace` depuis une commande il faut : 1. Créer un fichier texte nommé `rmspace` 2. Y mettre, *en toute première ligne*, `#!/bin/sh` puis la commande que l'on @@ -720,6 +711,6 @@ rarement les commandes/scripts comme des logiciels à proprement parler. [^2]: Oui, le caractère de retour à la ligne peut exister dans le nom d'un fichier [^3]: https://unix.stackexchange.com/questions/171346/security-implications-of-forgetting-to-quote-a-variable-in-bash-posix-shells/171347#171347 -[^4]: retrouver le texte de Cahzelas qui explique que `! -e` ne garantit par que +[^4]: retrouver le texte de Chazelas qui explique que `! -e` ne garantit par que le fichier n'existe pas 🤯 [^5]: https://unix.stackexchange.com/questions/204803/why-is-nullglob-not-default/204944#204944