Script bash : Bad substitution

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: 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

Salut,

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

#!/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 :wink:

C’est parmis mes tous premiers scripts :slightly_smiling:

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 :slightly_smiling:

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

#!/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 &

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 ?

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 :slightly_smiling:

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 :slightly_smiling:

@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 :slightly_smiling:

mode grognon on

j’aime pas grep et cut :stuck_out_tongue:
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 …

@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 ?

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:

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

est useless en faite :slightly_smiling:

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”

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

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

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

[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!

[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 :

C’est bien de la forme :

file=/home/tristan/Images/Backgrounds/imwaitingWS.jpg :question:

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…

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.

Dans :

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”.

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é.

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

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