# Script bash : Bad substitution

**URL:** <https://www.debian-fr.org/t/script-bash-bad-substitution/23993>\
**Category:** Programmation\
**Created:** [Février 20, 2016, 9:15 UTC](https://www.debian-fr.org/t/script-bash-bad-substitution/23993 "2016-02-20T21:15:11Z")\
**Posts on this page:** 17\
**Page:** 1

<div class="post-metadata">

**Author:** ![Koko\_le\_koala\_fou](https://www.debian-fr.org/letter_avatar_proxy/v4/letter/k/f1d935/32.png) [@Koko\_le\_koala\_fou](https://www.debian-fr.org/u/Koko_le_koala_fou)\
**Post date:** [Février 20, 2016, 9:15 UTC](https://www.debian-fr.org/t/script-bash-bad-substitution/23993/1 "2016-02-20T21:15:11Z")

</div>

Bonjour à tous, je cherchais à faire un script bash pour pouvoir changer de background facilement, et synchroniser celui-ci avec le thème slim (un lien symbolique est créé entre current.jpg de mon dossier Backgrounds, et le Background.jpg du thème slim)

Le problème est que lorsque j’éxecute le script, j’obtiens l’erreur suivante : [nitrogen.sh](http://nitrogen.sh): 3: Bad substitution

Avec le script suivant :

`#!/bin/bash
nitrogen ~/Images/Backgrounds
BG_DIR=${cat /home/tristan/.config/nitrogen/bg-saved.cfg | grep file | cut -d= -f2}
echo $BG_DIR
cp ${BG_DIR} /home/tristan/Images/Backgrounds/current.jpg
`

Sachant que la commande ligne 3 me donne comme résultat : /home/tristan/Images/Backgrounds/imwaitingWS.jpg, soit le chemin de mon wallpaper

Merci d’avance

---

<div class="post-metadata">

**Author:** ![zelogik](https://www.debian-fr.org/letter_avatar_proxy/v4/letter/z/58956e/32.png) [@zelogik](https://www.debian-fr.org/u/zelogik)\
**Post date:** [Février 20, 2016, 9:15 UTC](https://www.debian-fr.org/t/script-bash-bad-substitution/23993/2 "2016-02-20T21:15:11Z")

</div>

Salut,

Sans vouloir le vexer c’est pas très beau … ca ressemble a mes tous premiers scripts 😃

```auto
#!/bin/bash
if [-z "$HOME"]; then
 HOME="/home/tristan"
fi

exec nitrogen $HOME/Images/Backgrounds

BG_DIR=`cat $HOME/.config/nitrogen/bg-saved.cfg | grep file | cut -d= -f2`
echo $BG_DIR

cp $BG_DIR $HOME/Images/Backgrounds/current.jpg
```

A vu d’oeil sans essais ca me parait mieux 😉

---

<div class="post-metadata">

**Author:** ![Koko\_le\_koala\_fou](https://www.debian-fr.org/letter_avatar_proxy/v4/letter/k/f1d935/32.png) [@Koko\_le\_koala\_fou](https://www.debian-fr.org/u/Koko_le_koala_fou)\
**Post date:** [Février 20, 2016, 9:15 UTC](https://www.debian-fr.org/t/script-bash-bad-substitution/23993/3 "2016-02-20T21:15:12Z")

</div>

C’est parmis mes tous premiers scripts 🙂

Je ne me suis jamais vraiment penché sur la question auparavant, faisant plus ou moins tout en python, mais j’avais envie de tester comme ça 🙂

Le script marche bien, n’affiche plus d’erreurs, mais s’arrète avant le echo… et je n’arrive pas à comprendre pourquoi?

---

<div class="post-metadata">

**Author:** ![zelogik](https://www.debian-fr.org/letter_avatar_proxy/v4/letter/z/58956e/32.png) [@zelogik](https://www.debian-fr.org/u/zelogik)\
**Post date:** [Février 20, 2016, 9:15 UTC](https://www.debian-fr.org/t/script-bash-bad-substitution/23993/4 "2016-02-20T21:15:12Z")

</div>

```auto
#!/bin/bash
if [-z "$HOME"]; then
HOME="/home/tristan"
fi

echo 1
exec nitrogen $HOME/Images/Backgrounds
echo 2

BG_DIR=`cat $HOME/.config/nitrogen/bg-saved.cfg | grep file | cut -d= -f2`
echo 3
echo $BG_DIR
echo 4
cp $BG_DIR $HOME/Images/Backgrounds/current.jpg
echo fini

```

Voila une version de debug, a mon avis ca s’arrête vers:  
exec nitrogen $HOME/Images/Backgrounds

Met donc:  
exec nitrogen $HOME/Images/Backgrounds &

---

<div class="post-metadata">

**Author:** ![MisterFreez](https://www.debian-fr.org/letter_avatar_proxy/v4/letter/m/bb73d2/32.png) [@MisterFreez](https://www.debian-fr.org/u/MisterFreez)\
**Post date:** [Février 20, 2016, 9:15 UTC](https://www.debian-fr.org/t/script-bash-bad-substitution/23993/5 "2016-02-20T21:15:13Z")

</div>

Après un exec c’est dur de reprendre la main vu qu’il n’y a plus de shell. Pour rappel exec remplace le processus courant par celui passé en paramètre.

Moi je trouve pas si moche cette partie là du script.

Par contre :

[code]#!/bin/sh

nitrogen ${HOME}/Images/Backgrounds  
BG\_DIR=${grep “file” ${HOME}/.config/nitrogen/bg-saved.cfg | cut -d= -f2}  
echo $BG\_DIR  
cp ${BG\_DIR} ${HOME}/Images/Backgrounds/current.jpg[/code]  
C’est quand même mieux.

J’ai un peu du mal avec cut ça donne quoi -d=. Le séparateur est défini comme quoi ?

---

<div class="post-metadata">

**Author:** ![Koko\_le\_koala\_fou](https://www.debian-fr.org/letter_avatar_proxy/v4/letter/k/f1d935/32.png) [@Koko\_le\_koala\_fou](https://www.debian-fr.org/u/Koko_le_koala_fou)\
**Post date:** [Février 20, 2016, 9:15 UTC](https://www.debian-fr.org/t/script-bash-bad-substitution/23993/6 "2016-02-20T21:15:14Z")

</div>

Ok, alors, en effet, si je mets un & à la suite du exec nitrogen, ça execute bien la suite, mais par contre, ça l’execute trop vite. Du coup, j’ai gardé le nitrogen tout seul, et tout marche bien 🙂

Plus qu’à faire une conversion auto en jpg si le format est différent (j’ai des backgrounds en jpg et d’autres en png) avec imagemagik et tout ira bien 🙂

@MisterFreez : bah -d= me définit le séparateur comme “=”, on peut l’utiliser comme -d: ou autre. En gros, j’utilise cut assez normalement, je définis le symbole = comme séparateur, et je prends le deuxième élément.

Le script final :

[code]#!/bin/bash  
if [-z “$HOME”]; then  
HOME="/home/tristan"  
fi

nitrogen $HOME/Images/Backgrounds

BG\_DIR=`cat $HOME/.config/nitrogen/bg-saved.cfg | grep file | cut -d= -f2`  
echo $BG\_DIR  
cp $BG\_DIR $HOME/Images/Backgrounds/current.jpg  
echo fini[/code]

Merci à vous deux 🙂

---

<div class="post-metadata">

**Author:** ![zelogik](https://www.debian-fr.org/letter_avatar_proxy/v4/letter/z/58956e/32.png) [@zelogik](https://www.debian-fr.org/u/zelogik)\
**Post date:** [Février 20, 2016, 9:15 UTC](https://www.debian-fr.org/t/script-bash-bad-substitution/23993/7 "2016-02-20T21:15:14Z")

</div>

mode grognon on

j’aime pas grep et cut 😛  
et préfère awk!  
`cat $HOME/.config/nitrogen/bg-saved.cfg | grep file | cut -d= -f2`  
par  
`awk -F "=" '/file/ { print $2 }' $HOME/.config/nitrogen/bg-saved.cfg`

mode gnognon off

Ca enlève 2 pipes et utilise simplement la commande awk …

---

<div class="post-metadata">

**Author:** ![MisterFreez](https://www.debian-fr.org/letter_avatar_proxy/v4/letter/m/bb73d2/32.png) [@MisterFreez](https://www.debian-fr.org/u/MisterFreez)\
**Post date:** [Février 20, 2016, 9:15 UTC](https://www.debian-fr.org/t/script-bash-bad-substitution/23993/8 "2016-02-20T21:15:21Z")

</div>

@zelogik \> Excellent ! Je le savais mais je n’y pensais pas. J’aime ce mélange la recherche de faire au mieux. Pour cut je ne l’utilise jamais (awk power) pour grep je n’ai pas le réflexe parce que je ne me souviens jamais de la condition en awk.

En tout cas en gardant le grep et le cut il faut vraiment enlever ce cat qui ne sert à rien ! C’est terrible d’utiliser cat pour tout et n’importe quoi alors que les “Useless Use of cat” existe depuis des années. Là c’est un cas typique.

D’ailleurs ça sert à quoi ça ?

`if [-z "$HOME"]; then
    HOME="/home/tristan"
fi`  
HOME (surtout en majuscule est une variable d’environnement pas la peine de la définir.

[code]#!/usr/bin/awk  
BEGIN{  
FS="=";  
HOME="/home/tristan";  
system(“nitrogen “$HOME”/Images/Backgrounds”);  
}

/file/ { BG\_DIR = $2; }

END {  
system(“cp “$BG\_DIR” “$HOME”/Images/Backgrounds/current.jpg”);  
}[/code]  
Ça marche ça ?

---

<div class="post-metadata">

**Author:** ![zelogik](https://www.debian-fr.org/letter_avatar_proxy/v4/letter/z/58956e/32.png) [@zelogik](https://www.debian-fr.org/u/zelogik)\
**Post date:** [Février 20, 2016, 9:15 UTC](https://www.debian-fr.org/t/script-bash-bad-substitution/23993/9 "2016-02-20T21:15:32Z")

</div>

Bah en faite j’avais un doute sur la variable $HOME, si elle était défini par défaut par Debian ou si c’était moi qui l’avait créé dans l’un de mes nombreux script de démarrage perso.  
donc:

```auto
if [-z "$HOME"]; then
    HOME="/home/tristan"
fi
```

est useless en faite 🙂

Sinon je ne sais plus ou j’ai vu qu’il était conseillé de mettre:  
#!/usr/bin/env {python|awk|perl|stetuveux}  
Pour une meilleure portabilité “inter-distro/BSD-like/\*nix”

---

<div class="post-metadata">

**Author:** ![Koko\_le\_koala\_fou](https://www.debian-fr.org/letter_avatar_proxy/v4/letter/k/f1d935/32.png) [@Koko\_le\_koala\_fou](https://www.debian-fr.org/u/Koko_le_koala_fou)\
**Post date:** [Février 20, 2016, 9:15 UTC](https://www.debian-fr.org/t/script-bash-bad-substitution/23993/10 "2016-02-20T21:15:32Z")

</div>

Faudrait que je me mette à awk, ça a l’air plus sympa que le cat grep cut, et plus accessible 🙂

Vais me mettre à étudier sérieusement le bash moi.

---

<div class="post-metadata">

**Author:** ![Koko\_le\_koala\_fou](https://www.debian-fr.org/letter_avatar_proxy/v4/letter/k/f1d935/32.png) [@Koko\_le\_koala\_fou](https://www.debian-fr.org/u/Koko_le_koala_fou)\
**Post date:** [Février 20, 2016, 9:15 UTC](https://www.debian-fr.org/t/script-bash-bad-substitution/23993/11 "2016-02-20T21:15:46Z")

</div>

Le code final, si vous avez des suggestions pour l’améliorer, n’hésitez pas 🙂

[code]#!/bin/bash  
nitrogen $HOME/Images/Backgrounds

BG\_DIR=`awk -F "=" '/file/ { print $2 }' $HOME/.config/nitrogen/bg-saved.cfg`  
echo $BG\_DIR

case $BG\_DIR in  
\*.jpg)  
echo copie  
cp $BG\_DIR $HOME/Images/Backgrounds/current.jpg  
;;  
\*)  
echo conversion et copie  
convert $BG\_DIR $HOME/Images/Backgrounds/current.jpg  
;;  
esac[/code]

Je sais, le case est pas bien beau, mais je n’ai pas réussi à faire fonctionner un if pour faire la même chose. Probablement une erreur stupide, mais impossible de la trouver!

---

<div class="post-metadata">

**Author:** ![MisterFreez](https://www.debian-fr.org/letter_avatar_proxy/v4/letter/m/bb73d2/32.png) [@MisterFreez](https://www.debian-fr.org/u/MisterFreez)\
**Post date:** [Février 20, 2016, 9:15 UTC](https://www.debian-fr.org/t/script-bash-bad-substitution/23993/12 "2016-02-20T21:15:46Z")

</div>

[code]#!/bin/sh  
nitrogen $HOME/Images/Backgrounds

BG\_DIR=$(awk -F “=” ‘/file/ { print $2 }’ $HOME/.config/nitrogen/bg-saved.cfg)  
echo $BG\_DIR

echo $BG\_DIR | grep -i ‘\*.jpg’ \> /dev/null  
if [$? -eq 0]; then  
echo copie  
cp $BG\_DIR $HOME/Images/Backgrounds/current.jpg  
else  
echo conversion et copie  
convert $BG\_DIR $HOME/Images/Backgrounds/current.jpg  
fi[/code]  
Avec un if.

Sinon pour le awk il y a toujours le sed, ou la puissance des expressions régulière.  
A vu de nez, j’imagine que ça ça fonctionne :

```auto

```

C’est bien de la forme :

`file=/home/tristan/Images/Backgrounds/imwaitingWS.jpg` ❓

---

<div class="post-metadata">

**Author:** ![Koko\_le\_koala\_fou](https://www.debian-fr.org/letter_avatar_proxy/v4/letter/k/f1d935/32.png) [@Koko\_le\_koala\_fou](https://www.debian-fr.org/u/Koko_le_koala_fou)\
**Post date:** [Février 20, 2016, 9:15 UTC](https://www.debian-fr.org/t/script-bash-bad-substitution/23993/13 "2016-02-20T21:15:46Z")

</div>

En fait, si j’ai bien compris, on extrait la partie “.jpg” dans un fichier, et on vérifie que ce fichier n’est pas vide, c’est ça?

Sinon, les expressions régulières, je ne m’y suis pas encore mis. Il faut dire qu’à les regarder, ça ne donne pas envie…

---

<div class="post-metadata">

**Author:** ![MisterFreez](https://www.debian-fr.org/letter_avatar_proxy/v4/letter/m/bb73d2/32.png) [@MisterFreez](https://www.debian-fr.org/u/MisterFreez)\
**Post date:** [Février 20, 2016, 9:15 UTC](https://www.debian-fr.org/t/script-bash-bad-substitution/23993/14 "2016-02-20T21:15:47Z")

</div>

Petite modification :

[code]#!/bin/sh  
nitrogen $HOME/Images/Backgrounds

BG\_DIR=$(awk -F “=” ‘/file/ { print $2 }’ $HOME/.config/nitrogen/bg-saved.cfg)  
echo $BG\_DIR

echo $BG\_DIR | grep -q -i '\*.jpg’  
if [$? -eq 0]; then  
echo copie  
cp $BG\_DIR $HOME/Images/Backgrounds/current.jpg  
else  
echo conversion et copie  
convert $BG\_DIR $HOME/Images/Backgrounds/current.jpg  
fi[/code]

[quote]En fait, si j’ai bien compris, on extrait la partie “.jpg” dans un fichier, et on vérifie que ce fichier n’est pas vide, c’est ça?[/quote]Non on demande à grep de chercher un “.jpg” s’il ne le trouve pas il renvoie une erreur par son code de retour sinon le code de retour est 0.

> [@](#):
>
> Sinon, les expressions régulières, je ne m’y suis pas encore mis. Il faut dire qu’à les regarder, ça ne donne pas envie…

Dans :

```auto

```

on a “s” pour substitution. Les commandes de substitutions sont de la forme : s/expr/remplacement/  
Ou on remplace expr par remplacement.

Ici le expr c’est “^file=(._)$".  
[ul]  
[li]"^" : représente le début de la ligne. On s’assure ansi que la suite seras en début de ligne[/li]  
[li]“file=” : ben ça c’est juste pour qu’il cherche “file=” dans la ligne (au début de la ligne avec ce qu’on à mis avant)[/li]  
[li]"(bidule)" : les parenthèses sont protégées (le “” avant) pour que sed n’aille pas chercher des parenthèses dans la ligne. !l’utilité de ces parenthèses on les verras un peu plus loin.[/li]  
[li]"." : c’est le jocker il remplace n’importe quel caractère[/li]  
[li]"_” : on appelle ça un quantifier. là il signifie autant que l’on souhaite. Pour donner une idée “._" peut récupérer n’importe quoi[/li]  
[li]"$" : représente la fin de ligne, c’est pour m’assurer que "._” prend bien tout jusqu’à la fin.[/li][/ul]  
Donc résumons en enlevant les parenthèses :  
"^file=.\*$" permet de trouver toute chaine qui commencent par “file=” et qui possède ou une suite (quelque chose après le “=”). C’est ce qui va être substitué, c’est à dire que nous n’auront plus ça en sortis cela seras remplacé par la seconde partie de l’expression “s///”.

Cette seconde partie est plus simple “\1”. En faite avec les parenthèses j’ai fait une “capture” que je réutilise ici. Donc “\1” va être remplacé par ce qui a été récupéré par “.\*”. C’est pour cela que l’on utilise les parenthèses.

La dernière partie (après le dernier “/”) donne des options. La plus connus c’est “g” qui sert à permettre à la substitution à ce faire plusieurs fois par ligne. Ici p comme print permet d’afficher ce que l’on obtiens au final (utile avec l’option “-n”).

On aurait put utiliser “s/^file=//p”.

---

<div class="post-metadata">

**Author:** ![Koko\_le\_koala\_fou](https://www.debian-fr.org/letter_avatar_proxy/v4/letter/k/f1d935/32.png) [@Koko\_le\_koala\_fou](https://www.debian-fr.org/u/Koko_le_koala_fou)\
**Post date:** [Février 20, 2016, 9:15 UTC](https://www.debian-fr.org/t/script-bash-bad-substitution/23993/15 "2016-02-20T21:15:48Z")

</div>

Ouah, quand même, la dernière fois que je me suis retrouvé face à un truc aussi ésotérique, c’était le brainfuck.

A rajouter à la todo list, ça a l’air super puissant une fois maîtrisé.

---

<div class="post-metadata">

**Author:** ![MisterFreez](https://www.debian-fr.org/letter_avatar_proxy/v4/letter/m/bb73d2/32.png) [@MisterFreez](https://www.debian-fr.org/u/MisterFreez)\
**Post date:** [Février 20, 2016, 9:15 UTC](https://www.debian-fr.org/t/script-bash-bad-substitution/23993/16 "2016-02-20T21:15:50Z")

</div>

> [@](#):
>
> Ouah, quand même, la dernière fois que je me suis retrouvé face à un truc aussi ésotérique, c’était le brainfuck.

Le brainfuck fait peur mais c’est pas compliqué.

---

<div class="post-metadata">

**Author:** ![Koko\_le\_koala\_fou](https://www.debian-fr.org/letter_avatar_proxy/v4/letter/k/f1d935/32.png) [@Koko\_le\_koala\_fou](https://www.debian-fr.org/u/Koko_le_koala_fou)\
**Post date:** [Février 20, 2016, 9:15 UTC](https://www.debian-fr.org/t/script-bash-bad-substitution/23993/17 "2016-02-20T21:15:51Z")

</div>

Par ésotérique, j’entendais la syntaxe atroce. Mais les expressiosn régulières sont un poil plus utiles que le brainfuck.
