Contenu | Rechercher | Menus

Annonce

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.

À propos de l'équipe du forum.

#1 Le 14/03/2020, à 21:16

Akatu

Lister et regrouper des noms de fichiers en ajoutant du texte suppl.

Bonjour,

Pour bien exposer mon problème, je vous ai constitué un petit dossier, téléchargeable ici.

Dans le dossier Images, on retrouve :
- Dossier Base qui contient de vieilles images
- Dossier New qui contient des nouvelles images
Note : les images ont soit l'extension PNG soit WEBP

À la racine de l'archivage, on a le fichier final.xml qui doit inclure cette structure :

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <version>1</version>

    <category title="New" />
=> ICI ON LISTE LES ICÔNES DU DOSSIER NEW

    <category title="Voiture" />
=> ICI ON LISTE LES ICÔNES DU DOSSIER BASE COMMENÇANT PAR VOITURE_

    <category title="Camion" />
=> ICI ON LISTE LES ICÔNES DU DOSSIER BASE COMMENÇANT PAR CAMION_
</resources> 

Sur chaque ligne où on a une icône (sans extension), on doit avoir <item drawable=" devant le nom puis " /> après.

Dans chaque catégorie (New, base et voiture), les icônes doivent être listées par ordre alphabétique.

J'ai commencé à faire quelques bricoles en ligne de commande mais je suis encore loin du résultat. J'ai l'impression qu'il faut surtout passer par un script et je n'y connais rien...

Est-ce que quelqu'un aurait un peu de temps de dispo pour m'aider ?
Merci beaucoup !

Dernière modification par Akatu (Le 14/03/2020, à 21:18)


KDE neon User Edition
LENOVO Ideapad L340-15IRH
Intel(R) Core(TM) i5-9300H CPU @ 2.40GHz (8 coeurs)
512 Go SSD - (M.2 2280) PCIe 3.0 x4 - NVM Express (NVMe)

Hors ligne

#2 Le 14/03/2020, à 22:47

Watael

Re : Lister et regrouper des noms de fichiers en ajoutant du texte suppl.

salut,

eh ben, t'es mal barré.

les manipulations ne sont pas tout à fait les mêmes :
dans les deux cas, il faut ajouter (avec sed) sous le motif souhaité
- la liste/tableau des fichiers sous New (ça c'est facile)
- chaque nom de fichier comportant le motif souhaité sous le motif correspondant (ça c'est pas clair, je sais)
cela veut dire qu'il va falloir "découper" dans le nom de fichier la partie correspondante, et le mettre en capitale.
par exemple :
retrouver Voiture dans  Images/Base/voiture_1.png
ça se fait en plusieurs étapes en utilisant le Développement de variables du shell.

avance un peu sur le code, montre-nous ce que tu as fait, on t'aideras à aller au bout,
mais on ne fera pas ton boulot. en tout cas, pas moi.


Connected \o/
Welcome to sHell. · eval is evil.

Hors ligne

#3 Le 14/03/2020, à 23:09

Akatu

Re : Lister et regrouper des noms de fichiers en ajoutant du texte suppl.

Salut,

Je ne comprends pas le coup des majuscules. Toutes les icônes sont en minuscules. "Voiture" écrit ainsi dans final.xml n'est que le nom de la catégorie.

Via le terminal, j'ai trouvé comment lister les images "voiture" par exemple :

ls -1 voiture_* | sed -e 's/\.webp$//' | sed -e 's/\.png$//' > fichier_voiture.txt

Avec la commande cat je pense pouvoir me débrouiller pour fusionner les fichiers de sortie mais j'ai du mal à me dire que tout peut être fait dans un terminal. Et comme évoqué, je ne connais rien en script...


KDE neon User Edition
LENOVO Ideapad L340-15IRH
Intel(R) Core(TM) i5-9300H CPU @ 2.40GHz (8 coeurs)
512 Go SSD - (M.2 2280) PCIe 3.0 x4 - NVM Express (NVMe)

Hors ligne

#4 Le 15/03/2020, à 00:35

kamaris

Re : Lister et regrouper des noms de fichiers en ajoutant du texte suppl.

Tu peux faire ça en bash, en commençant par écrire le « préambule » :

echo '<?xml version="1.0" encoding="utf-8"?>
<resources>
    <version>1</version>

    <category title="New" />' > final.xml

Puis tu boucles sur le contenu du répertoire New :

for f in Images/New/*; do
  icon=${f##*/}
  echo "      <item drawable=\"${icon%.*}\" />"
done >> final.xml

Et puis tu continues de manière similaire pour le reste.

Hors ligne

#5 Le 15/03/2020, à 00:41

Watael

Re : Lister et regrouper des noms de fichiers en ajoutant du texte suppl.

c'est bizarre de ne pas laisser le chemin et l'extension des fichiers.


Connected \o/
Welcome to sHell. · eval is evil.

Hors ligne

#6 Le 15/03/2020, à 10:10

Akatu

Re : Lister et regrouper des noms de fichiers en ajoutant du texte suppl.

@kamaris Merci pour ton aide. Tu me donnes de l'espoir :-)
Je suis une tanche en script, j'y vais donc en mode "trial and error".

#!/bin/bash

echo '<?xml version="1.0" encoding="utf-8"?>
<resources>
    <version>1</version>

    <category title="New" />' > final.xml

for f in Images/New/*; do
  icon=${f##*/}
  echo "      <item drawable=\"${icon%.*}\" />"
done >> final.xml

Ce code est un bon début. J'ai voulu ajouter la partie suivante (Voiture) en mettant ceci à la suite :

echo '<category title="Voiture" />' > final.xml

Le problème c'est que ça écrase l'existant plutôt que d'ajouter à la suite.
EDIT : solution trouvée visiblement en remplaçant > par >>

echo '<category title="Voiture" />' >> final.xml

Autre problème, dans cette partie du code :

for f in Images/New/*; do
  icon=${f##*/}
  echo "      <item drawable=\"${icon%.*}\" />"
done >> final.xml

Comment distinguer par exemple les fichiers qui commencent par voiture_ ?

EDIT2 : je viens de penser à un truc. Il faudrait savoir comment des fichiers commençant par voiture_ par exemple mais aussi savoir comment lister des fichiers par exclusion. En fait, dans mes fichiers réels, j'ai plusieurs catégories puis une dernière qui contient "le reste" donc il faut que je puisse mettre "liste tous les fichiers sauf ceux commençant par xxx ou yyy ou zzz".

Dernière modification par Akatu (Le 15/03/2020, à 10:19)


KDE neon User Edition
LENOVO Ideapad L340-15IRH
Intel(R) Core(TM) i5-9300H CPU @ 2.40GHz (8 coeurs)
512 Go SSD - (M.2 2280) PCIe 3.0 x4 - NVM Express (NVMe)

Hors ligne

#7 Le 15/03/2020, à 10:30

Akatu

Re : Lister et regrouper des noms de fichiers en ajoutant du texte suppl.

Bon, j'avance, j'avance :-)
Il me reste finalement plus qu'à trouver la partie "tout lister sauf ce qui est déjà listé"

J'en suis là :

#!/bin/bash

#!/bin/bash

echo '<?xml version="1.0" encoding="utf-8"?>
<resources>
    <version>1</version>

    <category title="New" />' > final.xml

for f in Images/New/*; do
  icon=${f##*/}
  echo "      <item drawable=\"${icon%.*}\" />"
done >> final.xml

# catégorie VOITURE
echo '
	<category title="Voiture" />' >> final.xml

for f in Images/Base/voiture_*; do
  icon=${f##*/}
  echo "      <item drawable=\"${icon%.*}\" />"
done >> final.xml

# catégorie CAMION
echo '
	<category title="Camion" />' >> final.xml

for f in Images/Base/camion_*; do
  icon=${f##*/}
  echo "      <item drawable=\"${icon%.*}\" />"
done >> final.xml

# catégorie OTHERS
echo '
	<category title="Others" />' >> final.xml

Alors oui, il faut imaginer qu'il y ait aussi des images de motos, trains et avions dans le dossiers BASE et qu'on veut tout mettre dans la catégorie Others.


KDE neon User Edition
LENOVO Ideapad L340-15IRH
Intel(R) Core(TM) i5-9300H CPU @ 2.40GHz (8 coeurs)
512 Go SSD - (M.2 2280) PCIe 3.0 x4 - NVM Express (NVMe)

Hors ligne

#8 Le 15/03/2020, à 11:05

Akatu

Re : Lister et regrouper des noms de fichiers en ajoutant du texte suppl.

Je doute que ce soit la solution recommandée mais j'ai finalement trouvé.

# catégorie OTHERS
echo '
	<category title="Others" />' >> final.xml

for f in $(ls -1 Images/Base/* | grep -v '\voiture_' | grep -v '\camion_') ; do
icon=${f##*/}
  echo "<item drawable=\"${icon%.*}\" />"
done >> final.xml

KDE neon User Edition
LENOVO Ideapad L340-15IRH
Intel(R) Core(TM) i5-9300H CPU @ 2.40GHz (8 coeurs)
512 Go SSD - (M.2 2280) PCIe 3.0 x4 - NVM Express (NVMe)

Hors ligne

#9 Le 15/03/2020, à 13:39

Watael

Re : Lister et regrouper des noms de fichiers en ajoutant du texte suppl.

non. pas ls !

shopt -s extglob nullglob
for f in Images/Base/!(voiture|camion)*.{webp,png}; do ...; done

cf. help shopt
et
man -P 'less -p "^\s+Motifs génériques"' bash
et
man -P 'less -p "^\s+Développement des accolades"' bash


Connected \o/
Welcome to sHell. · eval is evil.

Hors ligne

#10 Le 15/03/2020, à 13:59

kamaris

Re : Lister et regrouper des noms de fichiers en ajoutant du texte suppl.

Avant de se lancer, tu pourrais regrouper tes diverses boucles for sous une autre boucle englobante, en faisant usage d'un tableau :

patterns=('camion' 'voiture')
for p in "${patterns[@]}"; do
  echo "
	  <category title=\"${p^}\" />" >> final.xml
  for f in "Images/Base/$p"*; do
    icon=${f##*/}
    echo "      <item drawable=\"${icon%.*}\" />"
  done
done >> final.xml

Ensuite, tu ajoutes la catégorie par défaut :

echo '
	<category title="Others" />' >> final.xml

regexp=$(IFS='|'; echo "${patterns[*]}")
for f in Images/Base/*; do
  icon=${f##*/}
  [[ $icon =~ $regexp ]] || echo "      <item drawable=\"${icon%.*}\" />"
done >> final.xml

J'ai rusé un peu pour construire la liste de motifs à exclure : je te laisse consulter man bash pour comprendre la syntaxe (voir les tableaux et la variable spéciale IFS).

---

NB : en bash, comme le propose Watael en #9, il existe un moyen simple pour exclure des motifs, avec la syntaxe

!(motif1|motif2|…|motifN)

en plus d'autres syntaxes du même style pour jouer avec des motifs.
Il est probable que chez toi, elles soient actives par défaut en interactif (dans le terminal), mais inactives dans un script ; il faut donc en général les activer par

shopt -s extglob

Dans le cas présent, pour la catégorie par défaut, ça donnerait

echo '
	<category title="Others" />' >> final.xml

ex_patterns=$(IFS='|'; echo "${patterns[*]}")
shopt -s extglob
for f in Images/Base/!(@($ex_patterns)*); do
  icon=${f##*/}
  echo "      <item drawable=\"${icon%.*}\" />"
done >> final.xml

Ici, ça marcherait, parce que les motifs (camion, voiture) ne contiennent pas d'espaces.
Mais si jamais ils devaient en contenir, ça ne marcherait plus, contrairement au code plus haut, qui lui marche dans tous les cas.
Je ne sais pas s'il est possible de faire marcher le second code quand il y a des espaces (sans lister en dur tous les motifs, bien entendu).

Dernière modification par kamaris (Le 15/03/2020, à 14:02)

Hors ligne

#11 Le 15/03/2020, à 14:21

Watael

Re : Lister et regrouper des noms de fichiers en ajoutant du texte suppl.

on peut passer par un case/esac :

for f in Images/Base/*
do
    case $f in
    *voiture*|*camion*) <ajouter sous sa catégorie>;;
    *) <ajouter sous others>;;
    esac
done

Dernière modification par Watael (Le 15/03/2020, à 14:22)


Connected \o/
Welcome to sHell. · eval is evil.

Hors ligne

#12 Le 15/03/2020, à 15:27

Akatu

Re : Lister et regrouper des noms de fichiers en ajoutant du texte suppl.

Merci pour vos nouveaux retours, je vais méditer là-dessus et faire d'autres tests.
Faut que ça reste assez simple car faudra que je puisse débugger si ça foire un jour :-)

Je note déjà la syntaxe pour les exclusions.

PS : les espaces sont interdits dans mes fichiers.

Dernière modification par Akatu (Le 15/03/2020, à 15:27)


KDE neon User Edition
LENOVO Ideapad L340-15IRH
Intel(R) Core(TM) i5-9300H CPU @ 2.40GHz (8 coeurs)
512 Go SSD - (M.2 2280) PCIe 3.0 x4 - NVM Express (NVMe)

Hors ligne

#13 Le 15/03/2020, à 15:36

Akatu

Re : Lister et regrouper des noms de fichiers en ajoutant du texte suppl.

Ça ne marche pas l'exclusion comme ça :

shopt -s extglob nullglob
for f in Images/Base/!(camion_|voiture_)*.{webp,png} ; do
icon=${f##*/}
  echo "<item drawable=\"${icon%.*}\" />"
done >> final.xml

J'ai les camion_ qui sont listés.


KDE neon User Edition
LENOVO Ideapad L340-15IRH
Intel(R) Core(TM) i5-9300H CPU @ 2.40GHz (8 coeurs)
512 Go SSD - (M.2 2280) PCIe 3.0 x4 - NVM Express (NVMe)

Hors ligne

#14 Le 15/03/2020, à 16:07

Watael

Re : Lister et regrouper des noms de fichiers en ajoutant du texte suppl.

!(voiture|camion)_*.{webp,png}

pourquoi le _ met le bazar ? je ne sais pas.


Connected \o/
Welcome to sHell. · eval is evil.

Hors ligne

#15 Le 15/03/2020, à 18:51

kamaris

Re : Lister et regrouper des noms de fichiers en ajoutant du texte suppl.

Oui, elle peut être un peu surprenante cette syntaxe de négation, car « !(voiture|camion) » signifie en fait « quelque chose différent de voiture ou camion, y compris rien », au sens où « rien » est bien quelque chose différent de voiture ou camion.
Donc quand on met « !(voiture|camion)*.{webp,png} », c'est en fait équivalent à « *.{webp,png} », c'est pourquoi il faut mettre quelque chose de discriminant en dehors des parenthèses avant l'étoile (par exemple un underscore).
C'est différent quand on utilise « @(voiture|camion) », qui signifie « quelque chose parmi voiture ou camion » (uniquement).

---

NB : ça reste un comportement un peu curieux ceci dit, car selon cette logique, on devrait pouvoir évacuer le cas « rien » par la syntaxe « !(voiture|camion|)*.{webp,png} », mais ça ne fonctionne pas.
Pourtant, cette syntaxe fonctionne s'il s'agit d'évacuer une chaine vide avant un underscore par exemple :

$ ls *.{webp,png}
_1.png  camion_1.webp  moto_1.webp  voiture_1.png
$ ls !(voiture|camion)_*.{webp,png}
_1.png  moto_1.webp
$ ls !(voiture|camion|)_*.{webp,png}
moto_1.webp
$ 

Par contre, on a

$ ls !(voiture|camion)*.{webp,png}
_1.png  camion_1.webp  moto_1.webp  voiture_1.png
$ ls !(voiture|camion|)*.{webp,png}
_1.png  camion_1.webp  moto_1.webp  voiture_1.png
$ 

Dernière modification par kamaris (Le 15/03/2020, à 20:37)

Hors ligne

#16 Le 15/03/2020, à 19:42

kamaris

Re : Lister et regrouper des noms de fichiers en ajoutant du texte suppl.

Il y a un moyen de gérer le cas avec espaces, dans la seconde syntaxe que je proposais en #10 :

ex_patterns=$(IFS='|'; echo "${patterns[*]}")
shopt -s extglob
(IFS=''; for f in Images/Base/!(@($ex_patterns)*); do
  icon=${f##*/}
  echo "      <item drawable=\"${icon%.*}\" />"
done >> final.xml)

où les parenthèses permettent de limiter la portée de la modification de l'IFS au sous-shell qu'elles définissent.
Mais je m'empresse d'ajouter que jouer avec l'IFS n'est pas forcément la meilleure chose à faire big_smile

Hors ligne

#17 Le 15/03/2020, à 20:45

Watael

Re : Lister et regrouper des noms de fichiers en ajoutant du texte suppl.

si les variables sont bien mises entre guillemets*, les espaces** dans les noms de fichiers ne devraient pas être problématiques.

j'ai raté un truc ?

--
* sauf cas particulier où ils sont facultatifs : [[, case/esac
** espace,tabulation,retour chariot


Connected \o/
Welcome to sHell. · eval is evil.

Hors ligne

#18 Le 15/03/2020, à 22:53

kamaris

Re : Lister et regrouper des noms de fichiers en ajoutant du texte suppl.

Le problème, c'est que là tu peux te retrouver avec quelque chose du style

ex_patterns='a b|c'

Donc si tu ne mets pas de guillemets, le shell va couper entre a et b, et si tu en mets, il va tout prendre d'un bloc : dans les deux cas, ça ne va pas.
Ce qu'il faudrait, pour engendrer un ex_patterns correct, c'est un truc qui cumule les propriétés de "${patterns[@]}" (protection de chaque élément du tableau) et de ${patterns[ * ]} (concaténation des éléments du tableau séparés par l'IFS), mais (sauf erreur) ça n'existe pas.

Hors ligne

#19 Le 16/03/2020, à 00:23

Watael

Re : Lister et regrouper des noms de fichiers en ajoutant du texte suppl.

ah, ok. on ne parlait pas de la même chose.
mais en effet, c'est frustrant.
ça ne passera pas non plus avec case/esac.

on peut, par contre, construire une regex et l'utiliser entre [[.
mais c'est moins drôle qu'avec un Développement étendu des chemins.


Connected \o/
Welcome to sHell. · eval is evil.

Hors ligne