Bonjour,
je ne suis pas un aficionados de sed, mais avec une pratique de vim je m’y retrouve.
J’ai résolu la question posée dans le titre ainsi, mais certains d’entre vous auront certainement mieux à proposer.
Il s’agit de renuméroter une série de fichiers dont le nom est sous la forme:
200_nomIdentique.xxx à 220_nomIdentique.xxx
[Correctif, voir plus bas: les noms ne sont pas identiques]
en ajoutant «1» au nombre initial.
Voici ma solution:
La ligne de commande:
—————————————————————
for i in {220..200} ; do j=$((i + 1)); F=$(echo ${i}*) ; f=$(echo "$F" | sed s/$i/$j/) ; echo "$F → $f" ; mv "$F" "$f" ; done
Explication:
—————————————————————
1 for i in {220..200} ; # Les numéros des noms de fichiers à remplacer
2 do
3 j=$((i + 1)); # nouvelle numérotation ( j = i+1 )
4 F=$(echo ${i}*) ; # nom du fichier initial (i)
5 f=$(echo "$F" | sed s/$i/$j/); # nom du fichier final ( s/$i/$j )
6 echo "$F → $f" ; # affichage pour vérifier
7 mv "$F" "$f" ; # remplacement effectif
8 done
(On remplace la ligne 6 par la ligne 7 si la ligne 6 affiche le résultat voulu.)
Numérotation autre qu’en préfixe:
——————————————————
Si le numéro est le seul nombre de la série (ici 200 à 220) dans les noms de tous les fichiers du répertoire, alors on peut faire ma même chose en ne modifiant que les jockers de la ligne 4.
Pas besoin de sed pour faire ce travail, bash a déjà tout ce qu’il faut pour ça :
Pour voir comment fonctionne l’extraction d’une sous-chaîne en fonction d’un caractère séparateur,
lance successivement les quatre lignes de commande suivantes :
for f in {220..200}_nomIdentique.xxx; do # Pour tous les noms de fichiers 200 à 220_nomIdentique.xxx
if test -f "$f"; then { # Si le fichier existe, alors
num=${f%_*} # Extraire le numéro qui précède le caractère `_`
numPlusUn=$((num + 1)) # Ajouter 1 à ce numéro
nvNom="$numPlusUn_nomIdentique.xxx" # Créer le nouveau nom de fichier
mv "$f" "$nvNom" # Renommer le fichier avec le nouveau numéro
}
done
Ce qui donne, en plus court :
for f in {220..200}_nomIdentique.xxx; do
[ -f "$f" ] && mv "$f" "$((${f%_*} + 1))_nomIdentique.xxx"
done
Et si tu veux que la commande mv affiche le travail qu’elle fait
utilise son option verbose :
mv --verbose "$f" "$nvNom"
ou bien, en option courte : (mais dans un script, autant utiliser l’option longue)
mv -v "$f" "$nvNom"
pour chaque fichier renommé,
ça affichera un message comme ci-dessous : renommé '220_nomIdentique.xxx' -> '221_nomIdentique.xxx'
J’utilise rename fréquemment, j’avais d’abord cherché de ce côté mais n’ai pas trouvé comment incrémenter le nombre en fonction de la cible. Le problème est: comment passer une variable bash au script rename en Perl?
Je trouve que la suppression d’une sous-chaîne dans une variable bash
est assez bien expliquée dans la page web suivante : wiki.bash-hackers.org → substring_removal
POST-SCRIPTUM
mon objectif était plus complexe qu’annoncé!
En effet la difficulté tenait à ce que les noms n’étaient pas totalement identiques!
Seule le numéro et le début de la chaîne le sont.
Dans ce cas, la solution de MicP me pose le même problème: comment récupérer la partie textuelle non identique (la partie supprimée par le code « %_*? »).
Désolé pour m’être trompé dans la question, mais votre réponse m’a tout de même déjà instruit et la question pourrait bien se poser en d’autres circonstances.
f="200_nomIdentique.xxx"
echo "$f" # J'affiche le nom du fichier contenu dans la variable `f`
echo "${f%_*}" # J'affiche ce qui est avant le caractère `_`
echo "${f#*_}" # => c'est peut-être ce que tu demandes : tout ce qui est après le caractère `_`
Effectivement, j’avais essayé de faire en fonction de ce que je lisais dans ton script
parce que je n’avais pas autre chose.
Il aurait fallu décrire un peu plus le contexte en donnant une liste de noms de fichiers avant, et après l’exécution du script en fonction de ce que tu souhaiterais obtenir
Parce que s’il est question d’un nomIdentique qui ne l’est pas,
alors le script que je t’ai proposé ne convient forcement pas du tout.
Donc, donne nous un exemple de liste représentative de fichiers que tu aurais au départ
et la liste de ces mêmes fichiers telle que tu souhaiterais la voir après le l’exécution du script.
le let numero2=$(echo $numero+1|bc); ermet d’éviter la conversion octale ainsi un fichier qui commence par 015 devient un fichier qui commence par 16 , pas par 14 ( = 1*8+5 +1 ), mais le zéro saute
Ma solution initiale avec sed fonctionne, bien que je vous ai égaré en négligeant à tord le fait que les noms n’étaient pas identiques.
(Je vais le préciser dans l’énoncé initiale)