Bonjour,
je souhaite réaliser un traitement par lots sur les noms de fichier (utiliser la commande rename en utilisant des metadonnées).
La syntaxe envisagée serait donc comme:
Renommer Truc*.jpg Truc*.JPG ./destination/
Ma question est donc comment récupérer les listes Truc*.jpg et Truc*.JPG dans un tableau du script.
Manifestement, la syntaxe suivante n’est pas la bonne:
#!/bin/bash
declare -a TableauDeFichiers
TableauDeFichiers="($1)"
for i in "${!TableauDeFichiers[@]}"
do
echo "Rang=$i - Nom=${TableauDeFichiers[$i]}"
done
Bonjour,
D’où provient ton tableau de fichier?
d’un fichier texte? d’une liste entrée à la main? autre chose?
Ayant oublié l’existence de rename, j’utilise mv
exemple pour renomme les .JPG en .jpg
find . -maxdepth 1 -name "*JPG" |while read fich;do fich2="$(echo $fich |sed 's#JPG$#jpg#')";mv "$fich" "$fich2";done
Bonjour
Une ligne de commande bash pour renommer en jpg
tous les fichiers du répertoire courant dont le nom d’extension serait JPG
for f in *.JPG; do [ -f "$f" ] && mv "$f" "${f%.JPG}.jpg"; done
Merci à tous , mais ma question est comment charger une liste dans un script, donc dans un tableau.
En gros:
comment utiliser une liste de fichiers comme « *.jpg » dans un script
monscript.sh *.jpg
(Ensuite la fonction de renommage sera une autre question… où mv sera effectivement peut-être la solution)
Dans mon (mauvais) exemple, j’espérais charger « $1 » dans un tableau, mais « $1 » n’est qu’un seul élément.
Cette remarque me fait penser qu’il existe la variable $@, qui récupère tous les paramètres, ici tous les noms de fichier!
[EDIT]
Pb NON résolu!
La liste des fichiers obtenue par
Tableau=« $@ » (ou $*) ne contient qu’un seul élément qui, cette fois est bien la liste complète, mais seulement comme 1er élément du tableau:
#!/bin/bash --
# Remplir un tableau passé au script
1er essai
declare -a fichiers
for f in ${!fichiers[@]} ;
do
echo "Rang=$f - fichier=${fichiers[$f]}"
done
# N'affiche rien
2e essai
declare -a TableauDeFichiers
TableauDeFichiers="($*)"
for i in "${!TableauDeFichiers[*]}"
do
echo "Rang=$i - Nom=${TableauDeFichiers[$i]} "
done
# Affiche la liste dans une seule variable scalaire, avec les parenthèses et
# l'entête unique « Rang=0 »
De ces 2 exemples, les variables $* et $@ donnent le même résultat.
Il provient d’une syntaxe du shell avec jockers (truc*.jpg par exemple).
Ce n’est pas la bonne syntaxe pour parcourir les indexes d’un tableau:
for i in ${!TableauDeFichiers[*]}
do
echo "Rang=$i - Nom=${TableauDeFichiers[$i]} "
done
Il n’y a pas de double quote dans la boucle for i in.
Mais si ton argument est « *.jpg » ca ne marchera pas. Car il faut qu’il puisse réaliser en fait ls *.jpg pour avoir une liste
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é…