Contenu | Rechercher | Menus

Annonce

Ubuntu 16.04 LTS
Commandez vos DVD et clés USB Ubuntu-fr !

Pour en savoir un peu plus sur l'équipe du forum.

Si vous avez des soucis pour rester connecté, déconnectez-vous puis reconnectez-vous depuis ce lien en cochant la case
Me connecter automatiquement lors de mes prochaines visites.

#1 Le 06/12/2017, à 18:02

AGP-Architecture

erreur avec sed dans un script

Bonsoir à tous,

je rencontre un problème avec sed dans un de mes scripts

voici le code utilisé

DOSSIERATRAITER="$1"

echo $DOSSIERATRAITER

NOMDOSSIER=$(basename "$DOSSIERATRAITER")

#nettoyage du nom du dossier
echo $NOMDOSSIER

# nettoyage des valeurs entre (), [], {}
NOMDOSSIER="$(sed 's/([^)]*)//g' "$NOMDOSSIER")" 

et l'erreur :

sed: erreur de lecture sur DossierA: est un dossier

je ne comprend pas puisque $NOMDOSSIER est une string sans référence à une arborescence. Est-ce que j'ai manqué un cast de type de variable (si ca existe en bash)

Dernière modification par AGP-Architecture (Le 06/12/2017, à 18:03)

Hors ligne

#2 Le 06/12/2017, à 18:10

pingouinux

Re : erreur avec sed dans un script

Bonsoir,
Si tu veux traiter une chaîne avec sed :

sed ..... <<<"$NOMDOSSIER"

mais ce que tu fais me paraît bien compliqué. Tu devrais donner un exemple de ce que tu veux faire.

En ligne

#3 Le 06/12/2017, à 18:36

AGP-Architecture

Re : erreur avec sed dans un script

merci pour l'aide pingouinux

En gros je souhaite faire un script pour renommer toute les images d'un dossier avec le nom du dossier (sans les blancs ni ce qui est entre parenthèse ou crochet) et une numérotation pour ensuite le zipper en cbz

donc :

dossier AbC diuy
            01.jpg
            02.jpg

devient

dossier AbC diuy
           AbcDiuy-001.jpg
           AbcDiuy-002.jpg

Voici le script complet en l'état actuel

#!/bin/bash

DOSSIERATRAITER="$1"
NOMDOSSIER=$(basename "$DOSSIERATRAITER")

#nettoyage du nom du dossier
# nettoyage des valeurs entre (), [], {}
NOMDOSSIER="$(sed 's/([^)]*)//g' "$NOMDOSSIER")" 
NOMDOSSIER="${NOMDOSSIER,,}" # Mise en minuscule
# Mise des premières lettre en majuscule
NOMDOSSIER="${NOMDOSSIER// /}" # Nettoyage des blancs

#parcours des fichiers du dossier

for FICHIER in "$DOSSIERATRAITER"*; do

	if [ $(find "$DOSSIERATRAITER" -maxdepth 1 -type d | wc -l) -ne 1 ]; then # si contient un dossier ne pas traiter
		ERREUR="contient un dossier"
		echo "$ERREUR"
		exit 2
	fi
	
	if [ -f "$FICHIER" ]; then
	
		EXT=${FICHIER##*.}
		echo -e "\t$FICHIER  -->>  $EXT"
		
		NUMERO=$(printf "%03d" $I)
			
        echo -e "\t$DOSSIERATRAITER$NOMDOSSIER$SEPARATEUR$NUMERO.$EXT"
        echo

        ((I++))
    
	fi

done

#on zip le dossier et on le renomme

#on le déplace

exit 0

Dernière modification par AGP-Architecture (Le 06/12/2017, à 19:05)

Hors ligne

#4 Le 06/12/2017, à 20:09

pingouinux

Re : erreur avec sed dans un script

Tu devrais sortir de la boucle le test pour savoir si DOSSIERATRAITER ne contient que des fichiers.
Comme je te l'ai indiqué en #2, le sed doit se faire ainsi

NOMDOSSIER="$(sed 's/([^)]*)//g' <<<"$NOMDOSSIER")" 

mais il ne supprime que les parenthèses et leur contenu.

En ligne

#5 Le 06/12/2017, à 20:40

AGP-Architecture

Re : erreur avec sed dans un script

ok...

merci je viens de mettre à jour mais ça me semble barbare de faire :

# nettoyage des valeurs entre (), [], {}
NOMDOSSIER="$(sed 's/([^)]*)//g' <<< "$NOMDOSSIER")"
NOMDOSSIER="$(sed 's/[[^)]*]//g' <<< "$NOMDOSSIER")"
NOMDOSSIER="$(sed 's/{[^)]*}//g' <<< "$NOMDOSSIER")"

NOMDOSSIER="${NOMDOSSIER,,}" # Mise en minuscule 
NOMDOSSIER="$(sed 's/^.\| [a-z]/\U&/g' <<< "$NOMDOSSIER")"
NOMDOSSIER="${NOMDOSSIER//-/}" #première lettre mot en majuscule

NOMDOSSIER="${NOMDOSSIER// /}" # Nettoyage des blancs

Est-il possible de simplifier?
Comment peut-on supprimer tous les caractère spéciaux tels que + = - * ? ...
Comment peut-on remplacer les caractères avec accent à sans accent facilement?

Je viens également de découvrir une grosse erreur dans la boucle. En effet le code 

for FICHIER in "$DOSSIERATRAITER"*; do

n'ordonne pas la liste comme je le souhaite
les fichiers 1 2 3 4 5 6 7 8 9 10 11 12 13 14 sont traités dans l'ordre suivant :  10 11 12 13 14 1 2 3 4 5 6 7 8 9

exemple resultat

/media/sf_D_DRIVE/Nouveau dossier/test/
test
Test
-----------------------------
fichier : /media/sf_D_DRIVE/Nouveau dossier/test/10.png
	/media/sf_D_DRIVE/Nouveau dossier/test/10.png  -->>  png
	/media/sf_D_DRIVE/Nouveau dossier/test/Test-001.png

fichier : /media/sf_D_DRIVE/Nouveau dossier/test/11.png
	/media/sf_D_DRIVE/Nouveau dossier/test/11.png  -->>  png
	/media/sf_D_DRIVE/Nouveau dossier/test/Test-002.png

fichier : /media/sf_D_DRIVE/Nouveau dossier/test/12.png
	/media/sf_D_DRIVE/Nouveau dossier/test/12.png  -->>  png
	/media/sf_D_DRIVE/Nouveau dossier/test/Test-003.png

... retour coupé pour lisibilité

fichier : /media/sf_D_DRIVE/Nouveau dossier/test/1.png
	/media/sf_D_DRIVE/Nouveau dossier/test/1.png  -->>  png
	/media/sf_D_DRIVE/Nouveau dossier/test/Test-007.png

fichier : /media/sf_D_DRIVE/Nouveau dossier/test/2.png
	/media/sf_D_DRIVE/Nouveau dossier/test/2.png  -->>  png
	/media/sf_D_DRIVE/Nouveau dossier/test/Test-008.png

fichier : /media/sf_D_DRIVE/Nouveau dossier/test/3.png
	/media/sf_D_DRIVE/Nouveau dossier/test/3.png  -->>  png
	/media/sf_D_DRIVE/Nouveau dossier/test/Test-009.png

fichier : /media/sf_D_DRIVE/Nouveau dossier/test/4.png
	/media/sf_D_DRIVE/Nouveau dossier/test/4.png  -->>  png
	/media/sf_D_DRIVE/Nouveau dossier/test/Test-010.png

...

Comment peut-on faire pour ordonner le résultat dans l'ordre de la numérotation avant le traitement de la boucle?

Dernière modification par AGP-Architecture (Le 06/12/2017, à 21:06)

Hors ligne

#6 Le 06/12/2017, à 21:18

pingouinux

Re : erreur avec sed dans un script

Tu peux déjà simplifier. Par exemple, cette ligne récupère le basename, supprime les couples de ( ), [ ], { } et leur contenu, ainsi que les espaces.

NOMDOSSIER=$(sed 's#.*/##;s#([^)]*)##g;s#\[[^]]*\]##g;s#{[^}]*}##g;s# ##g' <<<"$DOSSIERATRAITER")

Édité :
Cette commande supprime en plus quelques caractères spéciaux, et remplace quelques lettres accentuées :

NOMDOSSIER=$(sed 's#.*/##;s#([^)]*)##g;s#\[[^]]*\]##g;s#{[^}]*}##g;s#[ +=*?-]##g;s#[àâ]#a#g;s#[éèê]#e#g' <<<"$DOSSIERATRAITER")

Pour lister dans le bon ordre, essaye :

while read FICHIER
do
     .............................................
done < <(ls "$DOSSIERATRAITER"* | sort -V)

Dernière modification par pingouinux (Le 06/12/2017, à 21:36)

En ligne

#7 Le 06/12/2017, à 21:48

Watael

Re : erreur avec sed dans un script

hmm sad mauvaise idée d'utiliser ls, ou au moins mauvaise recommandation dans l'absolu.

l'ordre numérique est-il justifié par le traitement ?
a priori, non.


eval, c'est mal.

Hors ligne

#8 Le 06/12/2017, à 21:54

AGP-Architecture

Re : erreur avec sed dans un script

@Watael

L'ordre est très important dans le traitement. En effet, s'agissant d'ebook les numéro des pages sont numéroté dans l'ordre 1 2 3 4 5 6 7 8 9 10 11 12 13 ...à l'origine et représente l'ordre de lecture.
Il est donc nécessaire de conservé ce même ordre après renommage pour conserver l'ordre de lecture.

@pingouinux
le sort V donne ce résultat

drwxrwx--- 1 root vboxsf    4096 déc  6 20:28 ./
drwxrwx--- 1 root vboxsf       0 déc  6 21:44 ../
total 24904
-rwxrwx--- 1 root vboxsf 1059393 oct 30 14:42 4.png*
-rwxrwx--- 1 root vboxsf 1084156 oct 30 14:40 1.png*
-rwxrwx--- 1 root vboxsf 1115539 oct 30 14:41 2.png*
-rwxrwx--- 1 root vboxsf 1145940 oct 30 14:41 3.png*
-rwxrwx--- 1 root vboxsf 1169460 oct 30 14:43 7.png*
-rwxrwx--- 1 root vboxsf 1185656 oct 30 14:45 9.png*
-rwxrwx--- 1 root vboxsf 1192884 oct 30 14:42 5.png*
-rwxrwx--- 1 root vboxsf 1260625 oct 30 14:46 12.png*
-rwxrwx--- 1 root vboxsf 1401744 oct 30 14:46 15.png*
-rwxrwx--- 1 root vboxsf 1673509 oct 30 14:44 8.png*
-rwxrwx--- 1 root vboxsf 1701627 oct 30 14:46 13.png*
-rwxrwx--- 1 root vboxsf 1702463 oct 30 14:45 11.png*
-rwxrwx--- 1 root vboxsf 1706300 oct 30 14:42 6.png*
-rwxrwx--- 1 root vboxsf 1792748 oct 30 14:45 10.png*
-rwxrwx--- 1 root vboxsf 6278057 déc  4 21:19 14.png*

donc n'ordonne pas vraiment dans le bon sens j'ai également essayé avec -g même résultat.

Dernière modification par AGP-Architecture (Le 06/12/2017, à 21:54)

Hors ligne

#9 Le 06/12/2017, à 21:55

pingouinux

Re : erreur avec sed dans un script

Watael #7 a écrit :

mauvaise idée d'utiliser ls

On va pourtant lire un nom de fichier à la fois, y compris les espaces s'il y en a.

En ligne

#10 Le 06/12/2017, à 22:00

pingouinux

Re : erreur avec sed dans un script

@AGP-Architecture #8 :
Ton ls est peut-être un alias. Quel est le retour de

type ls

Montre la commande exacte que tu as lancée.

En ligne

#11 Le 06/12/2017, à 22:05

AGP-Architecture

Re : erreur avec sed dans un script

pingouinux a écrit :

@AGP-Architecture #8 :
Ton ls est peut-être un alias. Quel est le retour de

type ls

Montre la commande exacte que tu as lancée.

résultat de la commande :

 ls est un alias vers « ls --color=auto »

je sais pas si ca a de l'importance mais j'ai lancé la commende avec sort directement dans la console et non depuis le script.

En tout cas merci pour le temps que tu passes à me conseiller et pour te rssurer je viens de comprendre certaines chose en plus avec sed ;-)

complément :

[*****@agpadmin-VirtualBox Nouveau dossier]$ ll test/ | sort --sort human-numeric
drwxrwx--- 1 root vboxsf       0 déc  6 22:06 ../
drwxrwx--- 1 root vboxsf    4096 déc  6 22:06 ./
-rwxrwx--- 1 root vboxsf 1059393 oct 30 14:42 4.png*
-rwxrwx--- 1 root vboxsf 1084156 oct 30 14:40 1.png*
-rwxrwx--- 1 root vboxsf 1115539 oct 30 14:41 2.png*
-rwxrwx--- 1 root vboxsf 1145940 oct 30 14:41 3.png*
-rwxrwx--- 1 root vboxsf 1169460 oct 30 14:43 7.png*
-rwxrwx--- 1 root vboxsf 1185656 oct 30 14:45 9.png*
-rwxrwx--- 1 root vboxsf 1192884 oct 30 14:42 5.png*
-rwxrwx--- 1 root vboxsf 1260625 oct 30 14:46 12.png*
-rwxrwx--- 1 root vboxsf 1401744 oct 30 14:46 15.png*
-rwxrwx--- 1 root vboxsf 1673509 oct 30 14:44 8.png*
-rwxrwx--- 1 root vboxsf 1701627 oct 30 14:46 13.png*
-rwxrwx--- 1 root vboxsf 1702463 oct 30 14:45 11.png*
-rwxrwx--- 1 root vboxsf 1706300 oct 30 14:42 6.png*
-rwxrwx--- 1 root vboxsf 1792748 oct 30 14:45 10.png*
-rwxrwx--- 1 root vboxsf 6278057 déc  4 21:19 14.png*
total 24904
[*****@agpadmin-VirtualBox Nouveau dossier]$ 

Dernière modification par AGP-Architecture (Le 06/12/2017, à 22:09)

Hors ligne

#12 Le 06/12/2017, à 22:09

pingouinux

Re : erreur avec sed dans un script

Tu as dû lancer un ls -l, et le tri s'est effectué sur la taille des fichiers. Mais si tu ne montres pas ta commande exacte, pas moyen de deviner…

En ligne

#13 Le 06/12/2017, à 22:27

AGP-Architecture

Re : erreur avec sed dans un script

pingouinux a écrit :

Tu as dû lancer un ls -l, et le tri s'est effectué sur la taille des fichiers. Mais si tu ne montres pas ta commande exacte, pas moyen de deviner…

effectivement, désolé pas encore le reflex des alias il sont créer et je les utilise mais oublie encore que c'est une commande avec des paramètres prédéfinis
donc nouveau résultat qui semble bon :

[*****@agpadmin-VirtualBox Nouveau dossier]$ ls test/ | sort -n
1.png
2.png
3.png
4.png
5.png
6.png
7.png
8.png
9.png
10.png
11.png
12.png
13.png
14.png
15.png
[*****@agpadmin-VirtualBox Nouveau dossier]$ 

j'intègre ça dans le script demain soir et je reviens vous dire si c'est bon.

Hors ligne

#14 Le 06/12/2017, à 22:49

Watael

Re : erreur avec sed dans un script

On va pourtant lire un nom de fichier à la fois, y compris les espaces s'il y en a.

y compris les retours chariot s'il y en a, et là, patatra. sad

find ... -printf '%fµ%h\0' \
   | sort -Vz \
   | while IFS='µ' read -d '' -r fileName dirName; do
      : whatever with "$dirName" & "$fileName"
     done

Dernière modification par Watael (Le 06/12/2017, à 22:57)


eval, c'est mal.

Hors ligne

#15 Le 07/12/2017, à 07:09

pingouinux

Re : erreur avec sed dans un script

Ah oui, effectivement, si le nom contient \n ou \r, le résultat est fantaisiste…
Il faut quand même chercher les ennuis pour utiliser des noms pareils, mais on ne sait jamais…

En ligne

#16 Le 07/12/2017, à 07:51

Zakhar

Re : erreur avec sed dans un script

Et si le nom de fichier commence par un '-' c'est en général très amusant si vous avez oublié '--' dans les commandes pour dire que ce qui suit n'est plus des options. tongue

Démo :

$ touch -- '-y'
$ sed 's/a/b/' $( ls -- ?y )
sed : option invalide -- 'y'

Version correcte :

sed 's/a/b/' -- $( ls -- ?y )

"A computer is like air conditioning: it becomes useless when you open windows." (Linus Torvald)

Hors ligne

#17 Le 07/12/2017, à 08:16

AGP-Architecture

Re : erreur avec sed dans un script

@Watael
C est possible  d avoir un retour chariot dans le nom de dossier et fichier?
Parce que je vois pas comment faire.  Puisque lorsque on nomme ou renomme un fichier le enter valide la fin du nom.
Sinon que ferais tu a la place d un msg?

Hors ligne

#18 Le 07/12/2017, à 11:38

Watael

Re : erreur avec sed dans un script

$ > 'mon
fichier'
$ ls mon*
'mon'$'\n''fichier'

il y a pire

$ > '  
 '
$ ls ' '*
'  '$'\n'' '

je crois qu'on faire encore pire...

PS: le $ est le PROMPT.
le > est une redirection; touch est inutile pour créer un fichier.
et ls, tu n'essaieras pas de parcourir la sortie.

Dernière modification par Watael (Le 07/12/2017, à 11:42)


eval, c'est mal.

Hors ligne

#19 Le 07/12/2017, à 18:50

AGP-Architecture

Re : erreur avec sed dans un script

@Watael
Ok effectivement un ls peut poser problème avec \r ou \t. comment faire alors pour lister la totalité des fichiers sans ls ou pour éviter les problème?

Hors ligne

#20 Le 07/12/2017, à 19:07

Zakhar

Re : erreur avec sed dans un script

AGP-Architecture a écrit :

@Watael
C est possible  d avoir un retour chariot dans le nom de dossier et fichier?
Parce que je vois pas comment faire.  Puisque lorsque on nomme ou renomme un fichier le enter valide la fin du nom.
Sinon que ferais tu a la place d un msg?

Cela dépend du filesystem utilisé.

La réponse pour ext2/3/4 : tous les caractères sont autorisés dans un nom de fichier, sauf 2 : le zéro binaire (désignant la fin de chaîne en C, il te faudrait un autre indicateur pour donner la longueur du nom ça serait compliqué !) et le '/' qui indique la séparation des répertoires.

Pour les autres filesystems tu peux voir là : https://en.wikipedia.org/wiki/Compariso … le_systems

Exemple, FAT32:  Unicode except NUL, " * / : < > ? \ |

Le nom de fichier est considéré par le kernel comme un "buffer binaire". C'est donc ensuite le rôle de la "locale" que tu utilises qui va interpréter ce "buffer" comme de l'ISO8859-1, de l'UF8, etc... du moment que dans le codage utilisé tu as fait attention de ne pas autoriser les deux caractères cités ci-dessus, c'est à dire en hexa : 0x00 et 0x2F (décimal : 0 et 47). En aucune façon le kernel ne cherchera à "interpreter" ce buffer comme un truc qui fait du sens pour un humain (ce n'est pas son rôle, c'est le rôle des programmes "userspace" qui interagissent avec l'utilisateur).

Les pièges classiques quand tu fais du shell sont donc :
- les espaces (attention à bien mettre les 'quotes' : ", partout où c'est nécessaires)
- les retours charriot et autres caractères escape en tout genre
- le '-' en début de fichier qui, passé à une commande, lui fait confondre le nom de fichier avec une option. Pour cela la plupart des commandes qui en ont besoin ont l'option '--' qui dit : j'ai fini les options, maintenant ce sont des noms de fichier. En effet, avec un nom de fichier qui commence par "-" tu as beau mettre des quotes double/simples, rien ne change ce sera toujours lu comme une option sauf tu as mis '--' avant.

D'autres pièges plus subtils viennent de l'interprétation du "buffer binaire" selon un codage du jeu de caractère.
Linux fonctionne depuis longtemps avec UTF-8 par défaut... sauf que certains des utilitaires GNU ne sont toujours pas compatibles avec ça !..
Pour certains cela n'a strictement aucune importance -en principe-. Dans sed, quand tu vas faire une recherche d'un pattern, s'il contient des caractères non-ASCII, vu qu'ils sont UTF-8 eux-même la recherche du pattern fonctionne automatiquement.

Enfin ça progresse pour ça, par exemple

$ printf '%s' 'démo' | wc -c
5
$ printf '%s' 'démo' | wc -m
4

L'ancienne option -c qui voulait dire "caractère" est bien correctement documentée maintenant comme "byte".
La nouvelle option -m (comme "multibytes") compte bien les caractères dans la locale en cours (ici fr_FR.UTF-8)

Dernière modification par Zakhar (Le 07/12/2017, à 19:15)


"A computer is like air conditioning: it becomes useless when you open windows." (Linus Torvald)

Hors ligne

#21 Le 07/12/2017, à 19:09

Zakhar

Re : erreur avec sed dans un script

AGP-Architecture a écrit :

@Watael
Ok effectivement un ls peut poser problème avec \r ou \t. comment faire alors pour lister la totalité des fichiers sans ls ou pour éviter les problème?

Un find sera plus fiable, tu peux lui donner une commande à appliquer à chaque fichier trouvé correspondant à ce que tu cherches. Il va appliquer la commande à ce qu'il a trouvé comme fichier, quel que soit le nom du fichier avec autant de caractères bizarre que ce fichier puisse avoir.

Dernière modification par Zakhar (Le 07/12/2017, à 19:13)


"A computer is like air conditioning: it becomes useless when you open windows." (Linus Torvald)

Hors ligne

#22 Le 07/12/2017, à 19:33

AGP-Architecture

Re : erreur avec sed dans un script

Zakhar a écrit :

Un find sera plus fiable, tu peux lui donner une commande à appliquer à chaque fichier trouvé correspondant à ce que tu cherches. Il va appliquer la commande à ce qu'il a trouvé comme fichier, quel que soit le nom du fichier avec autant de caractères bizarre que ce fichier puisse avoir.

J'avais essayer le find mais j'ai plusieurs erreur différente pendant mes tests.

j'ai fait ca mais il mets  également le nom du dossier alors que je veux que le nom du fichier

[*****@agpadmin-VirtualBox Nouveau dossier]$ find test/ -maxdepth 1 -type f | sort -V
test/1.png
test/2.png
test/3.png
test/4.png
test/5.png
test/6.png
test/7.png
test/8.png
test/9.png
test/10.png
test/11.png
test/12.png
test/13.png
test/14.png
test/15.png

donc comment faire ca avec un find?

 while read FICHIER
do
     .............................................
done < <(ls "$DOSSIERATRAITER"* | sort -V) 

Hors ligne

#23 Le 07/12/2017, à 20:16

Watael

Re : erreur avec sed dans un script

AGP-Architecture a écrit :

@Watael
Ok effectivement un ls peut poser problème avec \r ou \t. comment faire alors pour lister la totalité des fichiers sans ls ou pour éviter les problème?

comme je l'ai fait au post #14.
tu l'as testé ? tel quel, ça ne correspond pas à ce que tu veux faire ?

Dernière modification par Watael (Le 07/12/2017, à 20:16)


eval, c'est mal.

Hors ligne

#24 Le 07/12/2017, à 20:18

AGP-Architecture

Re : erreur avec sed dans un script

@Watael

find ... -printf '%fµ%h\0' \
   | sort -Vz \
   | while IFS='µ' read -d '' -r fileName dirName; do
      : whatever with "$dirName" & "$fileName"
     done

Désolé mais suis pas assez avancé en bash. hmm J'ai rien compris sad à ce qu'il faut faire avec ça

Hors ligne

#25 Le 07/12/2017, à 21:24

Watael

Re : erreur avec sed dans un script

ce qu'il faut faire avec ça

?

: whatever with "$dirName" & "$fileName"

c'est-à-dire, ce que tu veux faire avec les noms du répertoire et du fichier.


eval, c'est mal.

Hors ligne