# SED Renuméroter les noms d'une liste de fichiers

**URL:** <https://www.debian-fr.org/t/sed-renumeroter-les-noms-dune-liste-de-fichiers/86719>\
**Category:** Programmation\
**Created:** [Juin 25, 2022, 5:30 UTC](https://www.debian-fr.org/t/sed-renumeroter-les-noms-dune-liste-de-fichiers/86719 "2022-06-25T17:30:06Z")\
**Posts on this page:** 13\
**Page:** 1

<div class="post-metadata">

**Author:** ![josephtux](https://www.debian-fr.org/user_avatar/www.debian-fr.org/josephtux/32/3985_2.png) [@josephtux](https://www.debian-fr.org/u/josephtux)\
**Post date:** [Juin 25, 2022, 5:30 UTC](https://www.debian-fr.org/t/sed-renumeroter-les-noms-dune-liste-de-fichiers/86719/1 "2022-06-25T17:30:06Z")

</div>

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:  
—————————————————————

```auto
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.

---

<div class="post-metadata">

**Author:** ![yatta](https://www.debian-fr.org/user_avatar/www.debian-fr.org/yatta/32/12132_2.png) [@yatta](https://www.debian-fr.org/u/yatta)\
**Post date:** [Juin 25, 2022, 6:47 UTC](https://www.debian-fr.org/t/sed-renumeroter-les-noms-dune-liste-de-fichiers/86719/2 "2022-06-25T18:47:12Z")

</div>

je ne pense pas que sed soit l’utilitaire le plus adapté pour ça.  
peut être regarder du coté de rename ?

---

<div class="post-metadata">

**Author:** ![anon29980398](https://www.debian-fr.org/letter_avatar_proxy/v4/letter/a/f4b2a3/32.png) [@anon29980398](https://www.debian-fr.org/u/anon29980398)\
**Post date:** [Juin 26, 2022, 3:52 UTC](https://www.debian-fr.org/t/sed-renumeroter-les-noms-dune-liste-de-fichiers/86719/3 "2022-06-26T03:52:23Z")

</div>

Bonjour

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 :

```auto
f="200_nomIdentique.xxx"
echo "$f"
echo "${f%_*}"
echo "${f#*_}"

```

* * *

Donc :

```auto
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 :

```auto
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` :

```auto
mv --verbose "$f" "$nvNom"

```

ou bien, en option courte : (mais dans un script, autant utiliser l’option longue)

```auto
mv -v "$f" "$nvNom"

```

pour chaque fichier renommé,  
ça affichera un message comme ci-dessous :  
`renommé '220_nomIdentique.xxx' -> '221_nomIdentique.xxx'`

---

<div class="post-metadata">

**Author:** ![josephtux](https://www.debian-fr.org/user_avatar/www.debian-fr.org/josephtux/32/3985_2.png) [@josephtux](https://www.debian-fr.org/u/josephtux)\
**Post date:** [Juin 26, 2022, 8:38 UTC](https://www.debian-fr.org/t/sed-renumeroter-les-noms-dune-liste-de-fichiers/86719/4 "2022-06-26T08:38:45Z")

</div>

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?

---

<div class="post-metadata">

**Author:** ![josephtux](https://www.debian-fr.org/user_avatar/www.debian-fr.org/josephtux/32/3985_2.png) [@josephtux](https://www.debian-fr.org/u/josephtux)\
**Post date:** [Juin 26, 2022, 8:39 UTC](https://www.debian-fr.org/t/sed-renumeroter-les-noms-dune-liste-de-fichiers/86719/5 "2022-06-26T08:39:54Z")

</div>

Merci et bravo,  
en effet bash est plein de ressources.

La syntaxe de

```auto
$((${f%_*} + 1))_nomIdentique.xxx

```

demande une bonne maîtrise de la langue 😉

En particulier, j’ignorais que bash acceptait le joker après l’opérateur «%».

---

<div class="post-metadata">

**Author:** ![josephtux](https://www.debian-fr.org/user_avatar/www.debian-fr.org/josephtux/32/3985_2.png) [@josephtux](https://www.debian-fr.org/u/josephtux)\
**Post date:** [Juin 26, 2022, 8:50 UTC](https://www.debian-fr.org/t/sed-renumeroter-les-noms-dune-liste-de-fichiers/86719/6 "2022-06-26T08:50:41Z")

</div>

Remarque:  
Il est essentiel de compter du plus haut vers le plus bas pour ne pas écraser chaque fichier par le premier.

---

<div class="post-metadata">

**Author:** ![anon29980398](https://www.debian-fr.org/letter_avatar_proxy/v4/letter/a/f4b2a3/32.png) [@anon29980398](https://www.debian-fr.org/u/anon29980398)\
**Post date:** [Juin 26, 2022, 9:03 UTC](https://www.debian-fr.org/t/sed-renumeroter-les-noms-dune-liste-de-fichiers/86719/7 "2022-06-26T09:03:24Z")

</div>

> [@josephtux](#):
>
> … j’ignorais que bash acceptait le joker après l’opérateur «%». …

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](https://wiki.bash-hackers.org/syntax/pe?s%5B%5D=substring#substring_removal)

Il y a aussi tout plein de liens concernant `bash`  
dans la page web suivante : [wiki.bash-hackers.org → start](https://wiki.bash-hackers.org/start)

---

<div class="post-metadata">

**Author:** ![dindoun](https://www.debian-fr.org/user_avatar/www.debian-fr.org/dindoun/32/4281_2.png) [@dindoun](https://www.debian-fr.org/u/dindoun)\
**Post date:** [Juin 26, 2022, 12:55 UTC](https://www.debian-fr.org/t/sed-renumeroter-les-noms-dune-liste-de-fichiers/86719/8 "2022-06-26T12:55:42Z")

</div>

> [@anon29980398](#):
>
> 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](https://wiki.bash-hackers.org/syntax/pe?s%5B%5D=substring#substring_removal)

je recommande à fond cette page

---

<div class="post-metadata">

**Author:** ![josephtux](https://www.debian-fr.org/user_avatar/www.debian-fr.org/josephtux/32/3985_2.png) [@josephtux](https://www.debian-fr.org/u/josephtux)\
**Post date:** [Juin 26, 2022, 1:55 UTC](https://www.debian-fr.org/t/sed-renumeroter-les-noms-dune-liste-de-fichiers/86719/9 "2022-06-26T13:55:12Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![anon29980398](https://www.debian-fr.org/letter_avatar_proxy/v4/letter/a/f4b2a3/32.png) [@anon29980398](https://www.debian-fr.org/u/anon29980398)\
**Post date:** [Juin 26, 2022, 3:28 UTC](https://www.debian-fr.org/t/sed-renumeroter-les-noms-dune-liste-de-fichiers/86719/10 "2022-06-26T15:28:13Z")

</div>

> [@josephtux](#):
>
> … comment récupérer la partie textuelle non identique  
> (la partie supprimée par le code « `%_*?` »).

```auto
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 `_`

```

* * *

> [@josephtux](#):
>
> … mon objectif était plus complexe qu’annoncé!, …

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.

Merci.

---

<div class="post-metadata">

**Author:** ![dindoun](https://www.debian-fr.org/user_avatar/www.debian-fr.org/dindoun/32/4281_2.png) [@dindoun](https://www.debian-fr.org/u/dindoun)\
**Post date:** [Juin 26, 2022, 3:31 UTC](https://www.debian-fr.org/t/sed-renumeroter-les-noms-dune-liste-de-fichiers/86719/11 "2022-06-26T15:31:42Z")

</div>

salut  
il faudrait préciser, mais tu peux toujours t’en sortir avec le sed :

actuellement, je l’écrirais ainsi :

```auto
mkdir -p temp; 
find . -maxdepth 1 -type f |while read fich; do fichier="$(basename $fich)" ; 
numero="$(echo $fichier |sed 's#^\([0-9]*\)[^0-9].*#\1#')";
reste="$(echo $fichier |sed 's#^[0-9]*\([^0-9].*\)#\1#')"; 
let numero2=$(echo $numero+1|bc);
cp ${numero}${reste} temp/$numero2${reste};
done

```

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

---

<div class="post-metadata">

**Author:** ![josephtux](https://www.debian-fr.org/user_avatar/www.debian-fr.org/josephtux/32/3985_2.png) [@josephtux](https://www.debian-fr.org/u/josephtux)\
**Post date:** [Juin 26, 2022, 7:08 UTC](https://www.debian-fr.org/t/sed-renumeroter-les-noms-dune-liste-de-fichiers/86719/12 "2022-06-26T19:08:21Z")

</div>

`${f#_*}`

limpide, évident . Comment n’y avoir pas pensé: ça me remet devant mon âge… Le cerveau aussi s’enkylose.

---

<div class="post-metadata">

**Author:** ![josephtux](https://www.debian-fr.org/user_avatar/www.debian-fr.org/josephtux/32/3985_2.png) [@josephtux](https://www.debian-fr.org/u/josephtux)\
**Post date:** [Juin 26, 2022, 7:11 UTC](https://www.debian-fr.org/t/sed-renumeroter-les-noms-dune-liste-de-fichiers/86719/13 "2022-06-26T19:11:46Z")

</div>

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)
