Merci Zargos,
donc si je comprends bien, un script bash ne peut jamais extraire un tableau avec la syntaxe monscript *jpg
;
il est nécessaire d’écrire quelque-chose comme: monscript $(ls -1 *jpg)
Normal, c’est du shell, donc ton argument n’est pas une fonction mais juste du texte. rien d’autre. Il te faut donc interpréter ce texte.
Bash possède une fonction pour créer un tableau à partir d’une entrée (comme un fichier ou la sortie d’une commande par exemple): mapfile
Si tu veux récupérer tes .jpg dans un tableau, tu peux faire quelque chose comme mapfile -t liste_jpg < <(ls -1 *.jpg)
Le -t
permet de supprimer le caractère de fin de ligne de chaque élément qui sera ajouté au tableau.
il me semble , après tests, que
liste_jpg=$(ls -1 *.jpg)
donne le même résultat
Cette obstination à vouloir faire un « tableau » à une seule colonne est surprenante.
Une liste de fichiers est juste une liste.
Les deux paramètres dont a besoin le script sont le répertoire de départ et celui de destination, rien de plus. Le reste relatif au tableau est de l’embrouillage inutile.
script « ren-jpg »:
#!/bin/bash
printf "Déplacement/renommage des fichiers .{jp*g,JP*G} en .jpg\n du répertoire $1 vers $2\n\n"
if [ ! -d "$2" ] ;then echo "le répertoire de destination n'existe pas" ;exit;fi
if [ -d "$1" ] ;then cd $1 ;else echo "le répertoire initial n'existe pas" ;exit;fi
counter=0
ls *.{jp*g,JP*G} &>/dev/null && for x in *.{jp*g,JP*G} ; do
mv "$x" "$2/${x%%.*}.jpg" && ((counter++))
done
echo "$counter fichiers traités"
exit
exemple
ren-jpg /tmp /tmp/dest2
Déplacement/renommage des fichiers .{jp*g,JP*G} en .jpg
du répertoire /tmp vers /tmp/dest2
9 fichiers traités
Autre proposition ne nécessitant pas de saisir le nom de répertoire pour le traitement dans le répertoire courant uniquement.
#!/bin/bash
if [ "$2" ] ; then
printf "Déplacement/renommage des fichiers .{jp*g,JP*G} en .jpg\n du répertoire $1 vers $2\n\n"
[ -d "$1" ] && cd "$1" || R='initial'
[ -d "$2" ] && D="$2" || R='de destination'
[ "$R" ] && printf "\e[35mle répertoire $R n'existe pas\n" && exit
else
D=$PWD
fi
counter=0
for x in $(ls |egrep -i '\.jpe?g$') ;do
mv -n "$x" "$D/${x%%.*}.jpg" && ((counter++))
done
echo "$counter fichiers jpeg traités"
exit
Bonjour,
mon projet est de réaliser un script qui utilise les méta-données de certains fichiers pour les renommer.
Le fonction du script nécessiterait donc que j’utilise effectivement une liste passée en option, et non un répertoire (ou alors un répertoire provisoire contenant la dite liste).
Si je les comprends bien, les solutions de Verner et de Dindoun semblent me suggérer de créer d’abord un répertoire contenant seulement la sélection des fichiers à traiter.
Je vais explorer celle de Sputnik33 dés que possible: mapfile, que je ne connaissais pas et qui répeond peut-être à ma question, bien que l’exemple ne convienne pas: je souhaite passer la liste en option au script et non utiliser une liste toute faite, interne au script, comme «ls -1 *jpg.
(Par exemple, la commande rename demande en 2e argument une liste, mais elle ne permet pas d’utiliser directement une métadonnée, comme le script que j’envisage.
Peut-être faudra-t-il utiliser Perl que j’ai un peu pratiqué, mais très basiquement, il y a trop longtemps, ou Python3 que je n’ai encore jamais pratiqué. Actuellement l’engagement de l’informatique prends déja trop de place pour que j’envisage ces plaisirs de découvrir de nouveaux horizons, ou d’en redécouvrir des anciens.
merci à tous les trois.
Un problème bien posé est déjà la moitié de la solution.
Incompréhensible pour moi entre 1er et 14 ième message.
Bon courage.
@Verner
vous avez totalement raison, mais j’ai beau le savoir, ça ne suffit pas à mon savoir-faire!
C’est en lisant vos patientes réponses que j’ai pu envisager d’autres usages, mais utilisant couramment rename, j’occultai effectivement cette fonctionnalité pourtant plus évidente.
Désolé, mais ma vieille névrose est sans doute mal adaptée à ce sport cérébral pratiqué de façon trop amateur .
Encore merci
L’importance de parfaitement comprendre un problème et donc de savoir l’énoncer correctement, avant d’essayer de le résoudre, est une remarque valable pour absolument tous les domaines.
Que ce soit pour renommer ou déplacer un fichier, la commande linux ne prendra en compte que le nom réel du fichier, et non un nom approximatif extrait de quelconques « méta-données », et uniquement que pour « certains fichiers ».
Inutile d’essayer de faire un script avec ce genre d’approximations.
Heureusement, j’espère effectivement avoir plus de savoir et de savoir-faire dans les domaines de la vie qui m’intéressent plus que l’informatique. Je partage vos exigences dans ces domaines où je le peux, y étant moins ignorant.
Donc en résumé, la partie renommage de fichiers jpeg à partir de meta-données dont la provenance n’est pas précisée, et exclusivement pour certains fichiers, demande une reformulation illustrée par quelques exemples pour pouvoir être testée, probablement dans un autre sujet plus clair. Impossible à deviner à partir des différentes tentatives d’explications.
Concernant le titre du sujet, et le script premier message qui laisse supposer que l’objectif est de présenter un tableau numéroté d’une liste de fichiers, la solution la plus simple est celle-ci:
$ ftest() { printf '%s\n' $@ |awk '{print NR,$0}' ;}
$ ftest fichierA.jpg fichierB.jpg fichierC.jpg
1 fichierA.jpg
2 fichierB.jpg
3 fichierC.jpg
Pas sûr d’avoir vraiment compris la demande initiale, mais s’il s’agit de renommer une liste de fichiers par une liste de noms, je procède à partir d’un fichier CSV à deux colonnes :
while IFS="," read -r oldname newname ; do mv "./files/$oldname" "./files/$newname" ; done < input.csv ;
Je crée le fichier CSV avec LibreOffice, mais c’est bien sûr faisable directement dans le script, suivant l’origine des données.
En espérant n’avoir pas répondu à côté…
Dans l’hypothèse où le travail de recherche de « méta-données » est déjà disponible en amont dans un fichier index.csv, une seule commande suffira pour renommer les fichiers:
Démonstration/préparation test:
$ mkdir /tmp/test ;cd /tmp/test ;touch {a,b,c}1.jpg
$ cat << EOF > index.csv
a1.jpg,a2.jpg
b1.jpg,b2.jpg
c1.jpg,c2.jpg
EOF
$ ls
a1.jpg b1.jpg c1.jpg
$ awk -F, '{system("mv "$1" "$2)}' index.csv
$ ls *.jpg
a2.jpg b2.jpg c2.jpg
La conclusion claire et sans appel est bien que la difficulté n’est pas dans le « comment » faire, mais dans le « quoi », la définition de ce qu’il faut faire, en fournissant un kit de test.
Toutes ces solutions sont intéressantes, et je vous en remercie.
Mais elles me disent comment faire autre-chose ce que je cherche.
Ma recherche est plus générale que le simple exemple de renommer en fonction de ses métadonnées (ça pourrait aussi bien être des extraits de texte ou d’autres informations… toutes choses que je sais ou pourrais faire en ligne de commande sur une liste).
La question initiale aurait due être, (indépendamment de l’exemple de renommage): est-il possible passer simplement à un script bash une liste de noms de fichiers donnée par des jockers bash, comme on peut le faire avec Perl5 et sa fonction glob (si je me souviens bien de mes très vieux souvenirs de débutant autodidacte).
Je viens de trouver, un vieux script oublié depuis longtemps, à peine modifié (boucle while pour utiliser facilement le nombre d’arguments).
La syntaxe ${!variable} de bash – que j’avais oubliée depuis longtemps – est une fonction «eval» sur la variable.
Le script suivant marche très simplement, à ma grande surprise (et peut-être à la votre?)
#!/bin/bash --
NBARG=$#
echo " $NBARG arguments reçus par le script"
i=0
while [[ "$i" -lt "$NBARG" ]]
do
((i++))
echo "Rang: $i → fichier: ${!i}"
done
#La syntaxe ${!variable} est une fonction «eval» sur $variable
Ce qui donne par exemple:
$TableauDArguments.sh *bkp r*txt
13 arguments reçus par le script
Rang: 1 → fichier: BKP_incrementale.bkp
Rang: 2 → fichier: IdentifierUSBrsync.sh.bkp
Rang: 3 → fichier: lscl.bkp
Rang: 4 → fichier: parallel.bkp
Rang: 5 → fichier: projet_latex.bkp
Rang: 6 → fichier: rsyncClevoSamsung2T.sh.bkp
Rang: 7 → fichier: rsyncClevoToshiba.sh.bkp
Rang: 8 → fichier: rsync_Elements.sh.INIbkp
Rang: 9 → fichier: svmi.bkp
Rang: 10 → fichier: rsyncECMbash.txt
Rang: 11 → fichier: rsyncSeagate4Tsimplifie.txt
Rang: 12 → fichier: rsyncStructureBug.txt
Rang: 13 → fichier: rsyncStructure.txt
Évidemment dans la boucle while, je peux enfin faire ce que je veux, comme:
Extraire un champs dans les metadonnées (par exemple champs date de la photo, à défaut champs de dernière modification, à défaut date du fichier) et l’utiliser pour renommer le fichier d’un nom plus humain!.
Je suis désolé ne n’avoir pas su m’expliquer plus clairement, mais surpris que ce script si simple fonctionne !
Bonjour
En utilisant la commande shift
:
#!/bin/bash
while test ! -z "$1"; do
((i++))
echo "$i -> '$1'"
shift
done
Pour aller directement à la page du manuel de bash
concernée par la commande shift
lancez la ligne de commande suivante :
man --pager='less -p "shift \["' bash
shift est effectivement plus simple et efficace.
J’ai préféré utiliser ici la variable « $# », parce qu’elle montre simplement qu’on peut passer à un script une liste de fichiers avec les jockers de bash.
[Hors sujet]
Et on pourrait même utiliser $#
pour inverser l’ordre de la numérotation :
#!/bin/bash
while test ! -z "$1"; do
echo "$# -> '$1'"
shift
done
[/Hors sujet]
Bonjour Désole du détarage mais
jhead -n%Y-%m-%d-%H-%M-%S *
renome tous les jpg avec l’heure de création par exemple.
-nunmom pour indiquer un nom en plus de la date
Bonjour,
Je me disais tout bas que la bonne méthode était peut - être de regarder $# pour parcourir $1 à $$#.