J’ai récemment eu à renommer toute une floppée de fichiers PDF en leur ajoutant un suffixe aléatoire. Rien de très compliqué, mais suffisamment répétitif pour ne pas le faire à la main. Bash peut très bien faire l’affaire.
L’idée est simple : parcourir tous les fichiers .pdf d’un dossier, récupérer leur nom sans extension, générer un suffixe aléatoire, puis créer un nouveau nom de fichier.
Voici la commande courte que j’utilisais au départ :
for f in *.pdf; do cp "$f" "${f%.*}-$RANDOM$RANDOM.${f##*.}"; doneCode language: JavaScript (javascript)
Vite fait, bien fait. Mais on peut l’améliorer un peu, surtout si les fichiers sont nombreux, si leurs noms contiennent des espaces, ou si l’on veut éviter tout risque d’écrasement.
Comprendre la commande
La boucle parcourt tous les fichiers PDF du dossier courant :
for f in *.pdf; do
...
doneCode language: JavaScript (javascript)
La variable $f contient le nom du fichier en cours. Les guillemets autour de "$f" sont importants, car ils permettent de gérer correctement les noms de fichiers qui contiennent des espaces.
Ensuite, cette partie récupère le nom du fichier sans son extension :
${f%.*}
Et celle-ci récupère l’extension :
${f##*.}Code language: PHP (php)
Le manuel Bash documente ces formes d’expansion de paramètres : ${parameter%word} supprime le plus court suffixe correspondant au motif, tandis que ${parameter##word} supprime le plus long préfixe correspondant au motif.
Enfin, $RANDOM génère un nombre pseudo-aléatoire. En l’utilisant deux fois, on obtient un suffixe un peu plus long :
$RANDOM$RANDOMCode language: PHP (php)
Exemple :
document.pdf
document-1587324061.pdfCode language: JavaScript (javascript)
Copier ou renommer les fichiers ?
Dans la commande d’origine, j’utilise cp. Les fichiers originaux sont donc conservés.
for f in *.pdf; do cp "$f" "${f%.*}-$RANDOM$RANDOM.${f##*.}"; doneCode language: JavaScript (javascript)
Si vous voulez vraiment renommer les fichiers, utilisez plutôt mv :
for f in *.pdf; do mv "$f" "${f%.*}-$RANDOM$RANDOM.${f##*.}"; doneCode language: JavaScript (javascript)
La différence est importante :
Vos mises à jour vous font peur ?
PHP 8.x qui casse un plugin, un thème qui n'est plus maintenu, une mise à jour de WooCommerce qui change tout — je gère les montées de version proprement, avec environnement de staging et rollback prévu.
Mettons votre stack à jour sans risque →cpcrée une copie avec un nouveau nom ;mvrenomme le fichier original ;cpest plus prudent pour un premier essai ;mvest plus direct, mais moins indulgent.
Les commandes cp et mv viennent de GNU Coreutils sur la plupart des distributions Linux. La documentation de mv précise aussi les options utiles comme --no-clobber ou --update selon les cas.
Faire un dry-run avant de renommer
Avant de lancer une commande qui renomme beaucoup de fichiers, je conseille toujours de faire un test à blanc. Le principe : afficher ce qui serait fait, sans modifier les fichiers.
for f in *.pdf; do
printf 'cp -- %q %q\n' "$f" "${f%.*}-$RANDOM$RANDOM.${f##*.}"
doneCode language: JavaScript (javascript)
Ou, pour une commande de renommage :
for f in *.pdf; do
printf 'mv -- %q %q\n' "$f" "${f%.*}-$RANDOM$RANDOM.${f##*.}"
doneCode language: JavaScript (javascript)
Si le résultat vous convient, remplacez printf par cp ou mv. C’est moins spectaculaire qu’un renommage raté, mais nettement meilleur pour la tension artérielle.
Éviter les collisions de noms
$RANDOM est pratique, mais il ne garantit pas une unicité absolue. Si vous renommez quelques fichiers, le risque de collision est faible. Si vous traitez des milliers de fichiers, mieux vaut être plus prudent.
On peut d’abord ajouter l’option -n avec cp ou mv pour éviter d’écraser un fichier existant. Dans GNU Coreutils, --no-clobber sert précisément à ne pas remplacer un fichier de destination existant.
for f in *.pdf; do
cp -n -- "$f" "${f%.*}-$RANDOM$RANDOM.${f##*.}"
doneCode language: JavaScript (javascript)
Ou avec mv :
for f in *.pdf; do
mv -n -- "$f" "${f%.*}-$RANDOM$RANDOM.${f##*.}"
doneCode language: JavaScript (javascript)
Le -- indique la fin des options. C’est utile si un nom de fichier commence par un tiret. Exemple classique : -document.pdf. Sans --, la commande pourrait croire qu’il s’agit d’une option.
Version plus robuste avec une boucle jusqu’à trouver un nom libre
Si l’on veut éviter les collisions proprement, on peut générer un nouveau nom tant qu’il existe déjà.
for f in *.pdf; do
[ -e "$f" ] || continue
base=${f%.*}
ext=${f##*.}
while :; do
new="${base}-$RANDOM$RANDOM.${ext}"
if [ ! -e "$new" ]; then
cp -- "$f" "$new"
break
fi
done
doneCode language: PHP (php)
Cette version vérifie que le nom généré n’existe pas déjà avant de copier le fichier. Elle évite donc d’écraser une destination existante.
La ligne suivante est aussi volontaire :
[ -e "$f" ] || continueCode language: JavaScript (javascript)
Elle évite un cas agaçant : si aucun fichier .pdf n’existe, Bash peut garder le motif *.pdf tel quel. Cette vérification permet de passer au fichier suivant, ou plutôt de ne rien faire.
Version avec shopt -s nullglob
Une autre manière de gérer le cas “aucun fichier trouvé” consiste à activer nullglob. Avec cette option, un motif qui ne correspond à rien disparaît au lieu de rester sous forme de texte.
shopt -s nullglob
for f in *.pdf; do
cp -- "$f" "${f%.*}-$RANDOM$RANDOM.${f##*.}"
doneCode language: JavaScript (javascript)
C’est propre dans un script. Dans un terminal interactif, pensez simplement que l’option reste active pour la session courante.
Suffixe plus lisible avec la date et l’heure
Un suffixe aléatoire n’est pas toujours le plus pratique. Si l’on veut pouvoir retrouver quand les fichiers ont été traités, un suffixe basé sur la date peut être plus lisible.
suffix=$(date +%Y%m%d-%H%M%S)
for f in *.pdf; do
[ -e "$f" ] || continue
cp -- "$f" "${f%.*}-${suffix}.${f##*.}"
doneCode language: JavaScript (javascript)
Exemple :
document.pdf
document-20260506-103512.pdfCode language: JavaScript (javascript)
Cette méthode est très utile pour des exports, des sauvegardes, des lots de factures, ou des fichiers générés par un script.
Suffixe vraiment unique avec uuidgen
Si l’objectif est d’éviter les collisions, uuidgen est une option plus robuste que $RANDOM.
for f in *.pdf; do
[ -e "$f" ] || continue
uuid=$(uuidgen)
cp -- "$f" "${f%.*}-${uuid}.${f##*.}"
doneCode language: JavaScript (javascript)
Exemple :
document-3f4f3c0e-9f1b-4d53-bd65-2c610de8fbf8.pdfCode language: JavaScript (javascript)
C’est un peu long, mais très pratique si l’unicité compte davantage que l’élégance du nom.
Suffixe court avec openssl
Pour obtenir un suffixe court, lisible et suffisamment aléatoire, on peut utiliser openssl rand :
for f in *.pdf; do
[ -e "$f" ] || continue
suffix=$(openssl rand -hex 4)
cp -- "$f" "${f%.*}-${suffix}.${f##*.}"
doneCode language: JavaScript (javascript)
Exemple :
document-a3f91c7b.pdfCode language: JavaScript (javascript)
C’est souvent un bon compromis : moins verbeux qu’un UUID, plus propre que deux $RANDOM.
Attention aux fichiers avec plusieurs points
La syntaxe utilisée fonctionne correctement avec des noms contenant plusieurs points.
Exemple :
facture.client.2026.pdfCode language: CSS (css)
Avec :
${f%.*}
on obtient :
facture.client.2026Code language: CSS (css)
Et avec :
${f##*.}Code language: PHP (php)
on obtient :
pdf
Le nouveau nom devient donc :
facture.client.2026-a3f91c7b.pdfCode language: CSS (css)
Préserver l’extension en minuscules ou majuscules
La boucle for f in *.pdf ne cible que les fichiers terminés par .pdf en minuscules. Si vous avez aussi des .PDF, il faut adapter.
Une première méthode consiste à activer nocaseglob :
shopt -s nullglob nocaseglob
for f in *.pdf; do
cp -- "$f" "${f%.*}-$RANDOM$RANDOM.${f##*.}"
doneCode language: JavaScript (javascript)
Cette version trouve .pdf, .PDF, .Pdf, etc. Elle conserve l’extension d’origine dans le nouveau nom.
Version récursive avec find
Si les PDF se trouvent dans plusieurs sous-dossiers, utilisez find. Cette version copie chaque PDF dans son dossier d’origine, avec un suffixe aléatoire.
find . -type f -iname '*.pdf' -print0 | while IFS= read -r -d '' f; do
dir=$(dirname -- "$f")
file=$(basename -- "$f")
base=${file%.*}
ext=${file##*.}
suffix=$(openssl rand -hex 4)
cp -- "$f" "$dir/${base}-${suffix}.${ext}"
doneCode language: PHP (php)
Le duo -print0 et read -d '' permet de gérer les noms de fichiers contenant des espaces, apostrophes, retours à la ligne ou autres petites horreurs parfaitement légales sur un système Unix.
Version avec renommage réel et journalisation
Si vous renommez les fichiers avec mv, il peut être utile de garder une trace des anciens et nouveaux noms.
log="rename-$(date +%Y%m%d-%H%M%S).log"
for f in *.pdf; do
[ -e "$f" ] || continue
suffix=$(openssl rand -hex 4)
new="${f%.*}-${suffix}.${f##*.}"
mv -- "$f" "$new"
printf '%s\t%s\n' "$f" "$new" >> "$log"
doneCode language: JavaScript (javascript)
Le fichier de log permet de savoir exactement ce qui a été renommé. C’est précieux si vous devez retrouver un ancien nom, vérifier un traitement ou expliquer ce que le script a fait. Toujours utile quand un dossier contient 842 PDF nommés “scan-final-v2.pdf”.
Version sous forme de script réutilisable
Pour réutiliser la commande proprement, on peut créer un petit script Bash.
#!/usr/bin/env bash
set -euo pipefail
shopt -s nullglob
extension="${1:-pdf}"
mode="${2:-copy}"
for f in *."$extension"; do
base=${f%.*}
ext=${f##*.}
suffix=$(openssl rand -hex 4)
new="${base}-${suffix}.${ext}"
case "$mode" in
copy)
cp -- "$f" "$new"
;;
move)
mv -- "$f" "$new"
;;
*)
printf 'Mode invalide: %s\n' "$mode" >&2
printf 'Utilisation: %s [extension] [copy|move]\n' "$0" >&2
exit 1
;;
esac
printf '%s -> %s\n' "$f" "$new"
doneCode language: PHP (php)
On le rend exécutable :
chmod +x rename-with-random-suffix.shCode language: JavaScript (javascript)
Puis on l’utilise ainsi :
# Copier les PDF avec suffixe.
./rename-with-random-suffix.sh pdf copy
# Renommer les PDF avec suffixe.
./rename-with-random-suffix.sh pdf move
# Traiter des JPG.
./rename-with-random-suffix.sh jpg copyCode language: PHP (php)
Mémo rapide
# Copier les PDF avec un suffixe aléatoire simple.
for f in *.pdf; do cp -- "$f" "${f%.*}-$RANDOM$RANDOM.${f##*.}"; done
# Renommer les PDF avec un suffixe aléatoire simple.
for f in *.pdf; do mv -- "$f" "${f%.*}-$RANDOM$RANDOM.${f##*.}"; done
# Copier sans écraser une destination existante.
for f in *.pdf; do cp -n -- "$f" "${f%.*}-$RANDOM$RANDOM.${f##*.}"; done
# Copier avec un suffixe court généré par OpenSSL.
for f in *.pdf; do suffix=$(openssl rand -hex 4); cp -- "$f" "${f%.*}-${suffix}.${f##*.}"; done
# Copier avec un suffixe date.
suffix=$(date +%Y%m%d-%H%M%S)
for f in *.pdf; do cp -- "$f" "${f%.*}-${suffix}.${f##*.}"; done
# Traiter aussi les extensions .PDF.
shopt -s nullglob nocaseglob
for f in *.pdf; do cp -- "$f" "${f%.*}-$RANDOM$RANDOM.${f##*.}"; doneCode language: PHP (php)
Conclusion
Pour ajouter rapidement un suffixe aléatoire à une liste de fichiers PDF, cette commande suffit dans beaucoup de cas :
for f in *.pdf; do cp -- "$f" "${f%.*}-$RANDOM$RANDOM.${f##*.}"; doneCode language: JavaScript (javascript)
Elle crée une copie de chaque fichier en conservant le nom d’origine, l’extension, et en ajoutant un suffixe pseudo-aléatoire.
Pour un traitement plus sérieux, je recommande plutôt une version avec openssl rand -hex 4, cp -n, un dry-run préalable, ou un fichier de log si vous utilisez mv.
Bash permet de faire cela en une ligne, mais une ligne qui renomme 500 fichiers mérite tout de même trois secondes de réflexion. C’est peu cher payé pour éviter un dossier transformé en confettis numériques.
Vos mises à jour vous font peur ?
PHP 8.x qui casse un plugin, un thème qui n'est plus maintenu, une mise à jour de WooCommerce qui change tout — je gère les montées de version proprement, avec environnement de staging et rollback prévu.
Mettons votre stack à jour sans risque →
