Contenu | Rechercher | Menus

Annonce

Si vous avez des soucis pour rester connecté, déconnectez-vous puis reconnectez-vous depuis ce lien en cochant la case
Me connecter automatiquement lors de mes prochaines visites.

À propos de l'équipe du forum.

#101 Le 19/04/2026, à 22:23

Watael

Re : [RESOLU] script mettre en conformité les noms de fichiers samba

que s'est-il passé avec COM et LPT ? pourquoi sont-ils "indicés" ?


Connected \o/
Welcome to sHell. · eval is evil.

En ligne

#102 Le 20/04/2026, à 05:38

iznobe

Re : [RESOLU] script mettre en conformité les noms de fichiers samba

Bonjour : https://learn.microsoft.com/fr-fr/windo … ing-a-file

N’utilisez pas les noms réservés suivants comme nom d’un fichier :

CON, PRN, AUX, NUL, COM0, COM1, COM2, COM3, COM4, COM5, COM6, COM7, COM8, COM9, COM¹, COM², COM³, LPT0, LPT1, LPT2, LPT3, LPT4, LPT5, LPT6, LPT7, LPT8, LPT9, LPT¹, LPT², et LPT³. Évitez également ces noms suivis immédiatement d’une extension ; par exemple, NUL.txt et NUL.tar.gz sont tous deux équivalents à NUL. Pour plus d’informations, consultez l’article Espaces de noms.

j ' ai retravaillé et " optimisé " le script :

#!/bin/bash

# Description des variables :
# $nomOriginal = nom complet rep ou fichier original
# $pathOriginal = chemin du repertoire original
# $nomModif = nom complet rep ou fichier modifié
# $pathModif = chemin du repertoire modifié
# $nomArgModif = nom dernier argument modifié
# FPNWE = chemin du fichier complet sans .ext = Full Path Name Without Extension
# $ext = extension du fichier le cas échéant sinon , renvoie le chemin complet du fichier.
# $fileNameWE = nom du fichier sans path , ni extension .

# --- Configuration ---
modif_activ=false  # true pour appliquer les modifications
all_spaces=false   # true pour remplacer tous les espaces
execDir=""         # Chemin ABSOLU du dossier cible (vide = PWD)
#### FIN ####

# --- Variables globales ---
declare -i LongPath=0 NbNOTScanned=0 NbRepScanned=0 NbFileScanned=0 NbRepModified=0 NbFileModified=0 NbRepNOTModified=0 NbFileNOTModified=0; Debut=$(date +%s);
declare log_error="/tmp/error.log" log_modifs="/tmp/modifs"
### Liste des fichiers exclus
Exclus=( CON PRN AUX NUL NULL COM{0..9} LPT{0..9} COM¹ COM² COM³ LPT¹ LPT² LPT³ CLOCK$ )

# --- Initialisation ---
shopt -s globstar nullglob
echo "liste des erreurs ( fichiers ou dossiers ) n ' ayant pas pu etre modifiés :" > "$log_error"
echo "-------------------" > "$log_modifs"

# --- Fonctions ---
clean_complete_name() { # Nettoie un nom de fichier/dossier
    local name="$1"

    # Nettoyage des espaces (début, fin, autour des /, multiples)
    name=$(printf '%s' "$name" | sed -E '
    s/^[[:space:]]+//;
    s/[[:space:]]+$//;
    s/[[:space:]]*\/[[:space:]]*/\//g;
    s/[[:space:]]+/ /g
    ')
    # Remplacement des caractères interdits
    if test "$all_spaces" = true; then
        name=$(printf '%s' "$name" | tr '><"|?*\\ :' '_________')
    else
        name=$(printf '%s' "$name" | tr '><"|?*\\:'  '________')
    fi

    printf '%s\n' "$name"
}

for nomOriginal in "${execDir:=$PWD}"/**/*; do
    if test -L "$nomOriginal"; then
        ((NbNOTScanned++))
        continue
    elif test -f "$nomOriginal"; then
        ((NbFileScanned++))
        ext=${nomOriginal##*.} # get extension without filename
        if test "$nomOriginal" != "$ext"; then # si le fichier comporte une extension
            FPNWE="${nomOriginal%.*}" # get filename without extension
            FPNWE=$(clean_complete_name "$FPNWE")

            fileNameWE=${FPNWE##*/} # get only filename
            if [[ "${Exclus[*]}" ==  *" $fileNameWE "*  ]]; then FPNWE+="_"; fi

            ext=$(clean_complete_name "$ext")
            nomModif="$FPNWE.$ext"            
        else
            nomModif=$(clean_complete_name "$nomOriginal")
            nomArgModif=$(echo "$nomModif" | grep -o '[^/]*$') # Récupére le dernier argument
            if [[ "${Exclus[*]}" ==  *" $nomArgModif "*  ]]; then nomModif+="_"; fi # Vérifions si le nom n'est pas interdit.
        fi
    else
        ((NbRepScanned++))
        nomModif=$(clean_complete_name "$nomOriginal")
    fi

    if [[ "$nomOriginal" != "$nomModif" ]]; then # si il y a un changement a effectuer        
        nomArgModif=$(echo "$nomModif" | grep -o '[^/]*$') # Récupére le dernier argument
        
        # le nom du chemin ne doit pas dépasser 256 en standard , et chemin étendu 32767 max , prefixe windows = "\\?\" .
        #if (( "${#nomArgModif}" >= 256 || "${#nomModif}" >= 32767 )) ; then # Vérifions si la longueur n'est pas excessive
        if (( "${#nomModif}" >= 256 )) ; then # Vérifions si la longueur n'est pas excessive
            ((LongPath++))
            echo "Le nom de chemin de fichier est trop long ! impossible de renommer '$nomOriginal' en '$nomModif'" >> "$log_error"
        fi

        if test -d "$nomOriginal"; then # si c' est un dossier
            if test -e "$nomModif"; then # on verifie si il existe un dossier du meme nom avant de renommer et si il est modifiable
                ((NbRepNOTModified++))
                echo "$NbRepNOTModified un dossier du meme nom existe deja : impossible de renommer '$nomOriginal' en '$nomModif'" >> "$log_error"
            elif test ! -w "$nomOriginal"; then
                ((NbRepNOTModified++))
                echo "$NbRepNOTModified permission refusée : impossible de renommer '$nomOriginal' en '$nomModif'" >> "$log_error"
            else # si pas de dossier du meme nom , on renomme
                if test "$modif_activ" = true; then
                    mkdir -p "$nomModif"
                    echo "on renomme le dossier : mkdir '$nomOriginal' ==> '$nomModif'"
                    ((NbRepModified++))
                    echo "$NbRepModified CREER_REP : mkdir '$nomModif'" >> "$log_modifs"
                fi
            fi
        elif test -f "$nomOriginal" ; then # si c est un fichier
            if test -e "$nomModif"; then # on verifie si il existe un fichier du meme nom avant de renommer et s ' il est modifiable
                ((NbFileNOTModified++))
                echo "$NbFileNOTModified un fichier du meme nom existe deja : impossible de renommer '$nomOriginal' en '$nomModif'" >> "$log_error"
            elif test ! -w "$nomOriginal"; then
                ((NbFileNOTModified++))
                echo "$NbFileNOTModified : permission refusée : impossible de renommer '$nomOriginal' en '$nomModif'" >> "$log_error"
            else # si pas de fichier du meme nom , on renomme
                pathOriginal=${nomOriginal%/*} # chemin du repertoire original
                pathModif=${nomModif%/*} # chemin apres modif
                if [[ "$pathOriginal" != "$pathModif" ]]; then # si les chemins sont differents , c' est que l' arborescence a été modifiée :
                    nomModif="$pathModif"/"$nomArgModif" # dans ce cas on utilise l' arborescence modifiée precedemment + le nom modifié du dernier argument pour la destination
                fi
                echo "renommage du fichier : mv '$nomOriginal' ==> '$nomModif'"
                if test "$modif_activ" = true; then
                    mv "$nomOriginal" "$nomModif"
                    NbFileModified+=1
                    echo "$NbFileModified RENOM : mv '$nomOriginal' en : '$nomModif'" >> "$log_modifs"
                fi
            fi
        fi
    fi
done

# --- Affichage récapitulatif ---
echo "$NbRepScanned dossiers et $NbFileScanned fichiers traités, $NbRepModified répertoires modifiés, $NbFileModified fichiers modifiés , le tout en $(($(date +%s)-Debut)) secondes."
(( NbNOTScanned )) && echo "$NbNOTScanned non traités."
echo;
(( NbFileModified || NbRepModified )) && echo "liste des dossiers et fichiers modifiés dans '/tmp/modifs'"
(( NbRepModified )) && echo "pour supprimer les dossiers vides , copiez collez la commande suivante : find '${execDir:=$PWD}' -type d -empty -delete"
echo;
if (( NbFileNOTModified || NbRepNOTModified || LongPath)); then
    echo "$NbFileNOTModified fichiers , $NbRepNOTModified répertoires n ' ayant pas pu etre modifiés"
    echo "vous avez $LongPath répertoires de taille trop importante."
    echo "liste des erreurs : cat '$log_error'"
    echo;
fi

Mais plus je décompose , plus il est lent ...
En tout cas , là l ' algo fonctionne parfaitement bien me semble t il :

iznobe@iznobe-PC-U2604:~/Scripts/test$ ls -l
total 28
-rw-r----- 1 iznobe iznobe    0 Apr 17 00:29 '   test :   .ino   '
-rw-r----- 1 iznobe iznobe   15 Apr 17 00:29 ' bash.sh '
-rw-rw-r-- 1 iznobe iznobe    6 Apr 17 00:29 '><"|?*\ :'
drwxrwxr-x 2 iznobe iznobe 4096 Apr 18 10:22  COM
-rw-rw-r-- 1 iznobe iznobe    5 Apr 18 10:37  COM0
drwxrwxr-x 2 iznobe iznobe 4096 Apr 18 10:24  COM5
-rw-r----- 1 iznobe iznobe    0 Apr 17 00:29  COM6
drwxrwxr-x 2 iznobe iznobe 4096 Apr 18 09:55  LPT
-rw-rw-r-- 1 iznobe iznobe    5 Apr 18 11:31  LPT0.sh
lrwxrwxrwx 1 iznobe iznobe   30 Apr 18 09:43  rename.sh -> /home/iznobe/Scripts/rename.sh
iznobe@iznobe-PC-U2604:~/Scripts/test$ bash ~/Scripts/rename.sh
renommage du fichier : mv '/home/iznobe/Scripts/test/><"|?*\ :' ==> '/home/iznobe/Scripts/test/_______ _'
renommage du fichier : mv '/home/iznobe/Scripts/test/ bash.sh ' ==> '/home/iznobe/Scripts/test/bash.sh'
renommage du fichier : mv '/home/iznobe/Scripts/test/COM0' ==> '/home/iznobe/Scripts/test/COM0_'
renommage du fichier : mv '/home/iznobe/Scripts/test/COM6' ==> '/home/iznobe/Scripts/test/COM6_'
renommage du fichier : mv '/home/iznobe/Scripts/test/LPT0.sh' ==> '/home/iznobe/Scripts/test/LPT0_.sh'
renommage du fichier : mv '/home/iznobe/Scripts/test/   test :   .ino   ' ==> '/home/iznobe/Scripts/test/test _.ino'
3 dossiers et 6 fichiers traités, 0 répertoires modifiés, 0 fichiers modifiés , le tout en 0 secondes.
1 non traités.


iznobe@iznobe-PC-U2604:~/Scripts/test$ 

Dernière modification par iznobe (Le 20/04/2026, à 08:26)

Hors ligne

#103 Le 21/04/2026, à 21:13

iznobe

Re : [RESOLU] script mettre en conformité les noms de fichiers samba

La même chose , en mieux , plus complet et plus rapide :

#!/bin/bash

sanitize() {
  shopt -s extglob;

  filename=$(basename "$1")
  directory=$(dirname "$1")

  name_clean=$(sed -E \
  -e 's/^[[:space:]]*//' \
  -e 's/[[:space:]]*$//' \
  -e 's/[[:space:]]*\/[[:space:]]*/\//g' \
  -e 's/[[:space:]]+/ /g' \
  -e 's/[\\/:\*\?\"<>\|\x01-\x1F\x7F]/_/g' \
  -e "s/'/_/g" \
  -e 's/\.+$//' \
  -e 's/[[:space:]]*\.[[:space:]]*([^.]+)$/.\1/' \
  -e 's/^\.*$//' \
  -e 's/^(nul|prn|con|lpt[0-9]|com[0-9]|aux|COM¹|COM²|COM³|LPT¹|LPT²|LPT³)(\.|$)/\1_\2/I' \
  -e 's/^[[:space:]]*$/NONAME/' <<< "$filename")
  # 1 Suppression des espaces en début de ligne
  # 2 Suppression des espaces en fin de ligne
  # 3 Remplace toute séquence d’espaces autour d’une barre oblique (/) par une seule barre oblique
  # 4 Remplacement des espaces multiples par un seul espace  
  # 5 Remplacement des caractères interdits par des underscores  
  # 6 Remplacement des apostrophes par des underscores
  # 7 Suppression des points en fin de nom
  # 8 Suppression des espaces juste avant et / ou apres le dernier point
  # 9 Suppression des noms ne contenant que des points  
  # 10 si nom exclu on ajoute le suffixe "_".  
  # 11 si espace ou vide => NONAME  
  
  if [ "$filename" != "$name_clean" ]; then  
    target="$directory/$name_clean"
    suffix=0    
    final_name="$target"
    
    # eviter les doublons et renommer correctement quand meme :
    while [ -e "$final_name" ]; do # Tant que le fichier cible existe déjà
      name="${name_clean##*/}"   # enlève le chemin
      ext=""

      if [[ "$name" == .* ]]; then
        base="${name:1}"   # enlève le point initial
        if [[ "$base" == *.* ]]; then
          ext="${base##*.}"
        fi
      else
        if [[ "$name" == *.* ]]; then
          ext="${name##*.}"
        fi
      fi
      # Permet de renommer le tout , car $ext est deinie a vide au départ
      final_name="${directory}/${name}_${suffix}${ext}"

      ((suffix++))
    done
    
    echo " => '$1' serait renommé en '$final_name'"
    #mv -v "$1"  "$directory/$name_clean"
  fi
}

export -f sanitize

sanitize_dir() {
  find "$1" -depth -exec bash -c 'sanitize "$0"' {} \;
}

sanitize_dir "$PWD"

Dernière modification par iznobe (Le 21/04/2026, à 21:24)

Hors ligne

#104 Le 21/04/2026, à 22:43

Watael

Re : [RESOLU] script mettre en conformité les noms de fichiers samba

pour le sed tu peux te dispenser de tous ces -e, et avoir seulement quatres apostrophes (au début, à la fin, et deux pour protéger celui de la substitution de l'apostrophe ! big_smile ).
plus besoin non plus des antislash en fin de lignes.

nameClean=$(sed -E '
    s/^[[:space:]]+//
    s/[[:space:]]+$//
    s/'\''/_/g
    #etc' <<<"$filename"

tu vois que tu peux aussi insérer des commentaires.

Dernière modification par Watael (Le 21/04/2026, à 22:44)


Connected \o/
Welcome to sHell. · eval is evil.

En ligne

#105 Le 22/04/2026, à 00:34

iznobe

Re : [RESOLU] script mettre en conformité les noms de fichiers samba

oui , j ' avais vu qu ' on pouvait faire sans les -e , mais pas qu ' on pouvait mettre des com en plus .
Du coup j ' ai modifié car ça me saoulait cette histoire , c ' est bien plus pratique comme ça !
Merci .

j ' ai aussi rectifié le mv commenté ... ,  et enlevé une variable inutile :

#!/bin/bash

sanitize() {
  shopt -s extglob;

  filename=$(basename "$1")
  directory=$(dirname "$1")

  name_clean=$(sed -E '
  s/^[[:space:]]*//                           # Suppression des espaces en début de ligne
  s/[[:space:]]*$//                           # Suppression des espaces en fin de ligne
  s/[[:space:]]*\/[[:space:]]*/\//g           # Remplace toute séquence d espaces autour d une barre oblique (/) par une seule barre oblique
  s/[[:space:]]+/ /g                          # Remplacement des espaces multiples par un seul espace
  s/['\''\\/:\*\?\"<>\|\x01-\x1F\x7F]/_/g     # Remplacement des apostrophes et des caractères interdits par des underscores
  s/\.+$//                                    # Suppression des points en fin de nom
  s/[[:space:]]*\.[[:space:]]*([^.]+)$/.\1/   # Suppression des espaces juste avant et / ou apres le dernier point
  s/^\.*$//                                   # Suppression des noms ne contenant que des points
  s/^(nul|prn|con|lpt[0-9]|com[0-9]|aux|COM¹|COM²|COM³|LPT¹|LPT²|LPT³)(\.|$)/\1_\2/I  # si nom exclu on ajoute le suffixe _
  s/^[[:space:]]*$/NONAME/' <<< "$filename")  # si espace ou vide => NONAME
  
  if test "$filename" != "$name_clean"; then
    suffix=0
    final_name="$directory/$name_clean"
    
    # eviter les doublons et renommer correctement quand meme :
    while test -e "$final_name"; do # Tant que le fichier cible existe déjà
      name="${name_clean##*/}"   # enlève le chemin
      base="$name"
      ext=""

      if [[ "$name" == .* ]]; then
        base="${name:1}"   # enlève le point initial
        if [[ "$base" == *.* ]]; then
          ext="${base##*.}"
          base="${base%.*}"
        fi
      else
        if [[ "$name" == *.* ]]; then
          ext="${name##*.}"
          base="${name%.*}"
        fi
      fi
      # Permet de renommer le tout ( les 4 possibilités ) , car $ext et $base sont definies au départ
      final_name="${directory}/${base}_${suffix}${ext}"

      ((suffix++))
    done
    
    echo " => '$1' serait renommé en '$final_name'"
    #mv -v "$1"  "$final_name"
  fi
}

export -f sanitize

sanitize_dir() {
  Debut=$(date +%s);
  find "$1" -depth -exec bash -c 'sanitize "$0"' {} \;
  echo "le tout en $(($(date +%s)-Debut)) secondes."
}

sanitize_dir "$PWD"

Dernière modification par iznobe (Le 22/04/2026, à 11:54)

Hors ligne

#106 Le 22/04/2026, à 12:16

iznobe

Re : [RESOLU] script mettre en conformité les noms de fichiers samba

j ' ai le meme probleme avec les 2 versions du script :

iznobe@m-pi3:~/test $ bash ~/samba_rename.sh
renommage du fichier : mv '/home/iznobe/test/*' ==> '/home/iznobe/test/_'
renommage du fichier : mv '/home/iznobe/test/><"|?* \\ :' ==> '/home/iznobe/test/______ __ _'
renommage du fichier : mv '/home/iznobe/test/><"|?*\ :' ==> '/home/iznobe/test/_______ _'
renommage du fichier : mv '/home/iznobe/test/COM6' ==> '/home/iznobe/test/COM6_'
renommage du fichier : mv '/home/iznobe/test/oiu*   ^poiopjh, $.  yu  / MAIS   !:;,ù$*^ô   .   FUCK' ==> '/home/iznobe/test/oiu_ ^poiopjh, $. yu/MAIS !_;,ù$_^ô.FUCK'
renommage du fichier : mv '/home/iznobe/test/  @pour , ù? @   ' ==> '/home/iznobe/test/@pour , ù_ @'
renommage du fichier : mv '/home/iznobe/test/  @pour , ù? @ *' ==> '/home/iznobe/test/@pour , ù_ @ _'
renommage du fichier : mv '/home/iznobe/test/  @pour , ù? @ * \\' ==> '/home/iznobe/test/@pour , ù_ @ _ __'
renommage du fichier : mv '/home/iznobe/test/  @pour , ù? @ \\  ' ==> '/home/iznobe/test/@pour , ù_ @ __'
renommage du fichier : mv '/home/iznobe/test/  @pour , ù? @ * \\ jk  ' ==> '/home/iznobe/test/@pour , ù_ @ _ __ jk'
renommage du fichier : mv '/home/iznobe/test/   test :   .    ino   ' ==> '/home/iznobe/test/test _.ino'
renommage du fichier : mv '/home/iznobe/test/   test :   .ino   ' ==> '/home/iznobe/test/test _.ino'

renommage du fichier : mv '/home/iznobe/test/ test .  test /  test  .   test  ' ==> '/home/iznobe/test/test . test/test.test'
renommage du fichier : mv '/home/iznobe/test/ test .  test / test .  test ' ==> '/home/iznobe/test/test . test/test.test'

2 dossiers et 20 fichiers traités, 0 répertoires modifiés, 0 fichiers modifiés , le tout en 1 secondes.


1 fichiers , 0 répertoires n ' ayant pas pu etre modifiés
vous avez 0 répertoires de taille trop importante.
liste des erreurs : cat '/tmp/error.log'

iznobe@m-pi3:~/test $

et

iznobe@m-pi3:~/test $ bash ~/sanitize.sh
=> '/home/iznobe/test/  @pour , ù? @ * \\' serait renommé en '/home/iznobe/test/@pour , ù_ @ _ __'
=> '/home/iznobe/test/><"|?* \\ :' serait renommé en '/home/iznobe/test/______ __ _'
=> '/home/iznobe/test/   test :   .    ino   ' serait renommé en '/home/iznobe/test/test _.ino'
=> '/home/iznobe/test/  @pour , ù? @ \\  ' serait renommé en '/home/iznobe/test/@pour , ù_ @ __'
=> '/home/iznobe/test/><"|?*\ :' serait renommé en '/home/iznobe/test/_______ _'
=> '/home/iznobe/test/  @pour , ù? @ * \\ jk  ' serait renommé en '/home/iznobe/test/@pour , ù_ @ _ __ jk'
=> '/home/iznobe/test/  @pour , ù? @ *' serait renommé en '/home/iznobe/test/@pour , ù_ @ _'
=> '/home/iznobe/test/COM6' serait renommé en '/home/iznobe/test/COM6_'

 => '/home/iznobe/test/ test .  test /  test  .   test  ' serait renommé en '/home/iznobe/test/ test .  test /test.test'
 => '/home/iznobe/test/ test .  test / test .  test ' serait renommé en '/home/iznobe/test/ test .  test /test.test'
 => '/home/iznobe/test/ test .  test ' serait renommé en '/home/iznobe/test/test.test'

=> '/home/iznobe/test/   test:   fichier de test    % ?   ' serait renommé en '/home/iznobe/test/test_ fichier de test % __0'
=> '/home/iznobe/test/  @pour , ù? @   ' serait renommé en '/home/iznobe/test/@pour , ù_ @'
=> '/home/iznobe/test/   test :   .ino   ' serait renommé en '/home/iznobe/test/test _.ino'
=> '/home/iznobe/test/*' serait renommé en '/home/iznobe/test/_'
=> '/home/iznobe/test/oiu*   ^poiopjh, $.  yu  / MAIS   !:;,ù$*^ô   .   FUCK' serait renommé en '/home/iznobe/test/oiu*   ^poiopjh, $.  yu  /MAIS !_;,ù$_^ô.FUCK'
=> '/home/iznobe/test/oiu*   ^poiopjh, $.  yu  ' serait renommé en '/home/iznobe/test/oiu_ ^poiopjh, $.yu'
le tout en 1 secondes.
iznobe@m-pi3:~/test $

je me retrouve au final avec 2 fichiers du meme nom dans un dossier , si je ne dis pas de betises roll
Avec un point bonus pour le sanitize : le dossier qui contient les fichiers est correctement renommé .

Dernière modification par iznobe (Le 22/04/2026, à 12:20)

Hors ligne

#107 Le 22/04/2026, à 13:03

Watael

Re : [RESOLU] script mettre en conformité les noms de fichiers samba

je me retrouve au final avec 2 fichiers du meme nom dans un dossier , si je ne dis pas de betises roll

ce qui n'est pas possible : le dernier trouvé écrasera le précédent. sad
mv a des options pour éviter ça (en ajoutant un suffixe numérique), mais le script pour l'instant ne peut pas le (pré)dire, et mv, que je voie, n'a pas d'option "dry-run".


Connected \o/
Welcome to sHell. · eval is evil.

En ligne

#108 Le 22/04/2026, à 13:27

iznobe

Re : [RESOLU] script mettre en conformité les noms de fichiers samba

l ' idéal , serait donc de commencer par renommer les dossiers avant les fichiers , puis de vérifier les noms de fichiers , non ?

Autre chose , dans le script samba_rename.h , je ne vois pas de :  echo "on renomme le dossier : mkdir '$nomOriginal' ==> '$nomModif'"
Ce qui n' est pas normal , car justement , il est censé renommer d ' abord les dossiers :

          if test -d "$nomOriginal"; then # si c' est un dossier
            if test -e "$nomModif"; then # on verifie si il existe un dossier du meme nom avant de renommer et si il est modifiable
                ((NbRepNOTModified++))
                echo "$NbRepNOTModified un dossier du meme nom existe deja : impossible de renommer '$nomOriginal' en '$nomModif'" >> "$log_error"
            elif test ! -w "$nomOriginal"; then
                ((NbRepNOTModified++))
                echo "$NbRepNOTModified permission refusée : impossible de renommer '$nomOriginal' en '$nomModif'" >> "$log_error"
            else # si pas de dossier du meme nom , on renomme
                if test "$modif_activ" = true; then
                    mkdir -p "$nomModif"
                    echo "on renomme le dossier : mkdir '$nomOriginal' ==> '$nomModif'"
                    ((NbRepModified++))
                    echo "$NbRepModified CREER_REP : mkdir '$nomModif'" >> "$log_modifs"
                fi
            fi
        elif test -f "$nomOriginal" ; then # si c est un fichier
...

EDIT , juste le echo qui était mal placé , il faut le mettre :

else # si pas de dossier du meme nom , on renomme
                echo "on renomme le dossier : mkdir '$nomOriginal' ==> '$nomModif'"
                if test "$modif_activ" = true; then
                    mkdir -p "$nomModif"

Dernière modification par iznobe (Le 22/04/2026, à 13:55)

Hors ligne

#109 Le 22/04/2026, à 13:42

Watael

Re : [RESOLU] script mettre en conformité les noms de fichiers samba

l ' idéal , serait donc de commencer par renommer les dossiers avant les fichiers , puis de vérifier les noms de fichiers , non ?

je crois que non.
ce qui est dans le dossier est renommé - si un fichier/dossier existe mv lui ajoutera un suffixe, quel que soit la direction

Dernière modification par Watael (Le 22/04/2026, à 15:48)


Connected \o/
Welcome to sHell. · eval is evil.

En ligne

#110 Le 22/04/2026, à 15:42

iznobe

Re : [RESOLU] script mettre en conformité les noms de fichiers samba

En fait ça fonctionne bien si le " mv " est activé avec le script sanitize qui lui , gère les doublons .
le echo ne reflète pas tout forcément roll

Par contre , ce n' est pas le cas du samba_rename qui ne gere pas les doublons ( et pas correctement les espaces dans les noms de dossiers et autour des '.' .

Dernière modification par iznobe (Le 22/04/2026, à 16:29)

Hors ligne

#111 Le 22/04/2026, à 18:36

iznobe

Re : [RESOLU] script mettre en conformité les noms de fichiers samba

le script " tout pas beau " samba_rename :

récapitulatif :
383 dossiers et 5374 fichiers traités, 0 répertoires modifiés, 0 fichiers modifiés , le tout en 43 secondes.

le sanitize : 88 secondes mad lol

les 2 fonctionnent maintenant .
le script sanitize.sh gère les renommages  avec suffixe _X ( ou X est un numéro ) dans le cas ou le fichier existe déjà :

#!/bin/bash

sanitize() {
  shopt -s extglob;

  filename=$(basename "$1")
  directory=$(dirname "$1")

  name_clean=$(sed -E '
  s/^[[:space:]]*//                           # Suppression des espaces en début de ligne
  s/[[:space:]]*$//                           # Suppression des espaces en fin de ligne
  s/[[:space:]]*\/[[:space:]]*/\//g           # Remplace toute séquence d espaces autour d une barre oblique (/) par une seule barre oblique
  s/[[:space:]]+/ /g                          # Remplacement des espaces multiples par un seul espace
  s/['\''\\/:\*\?\"<>\|\x01-\x1F\x7F]/_/g     # Remplacement des apostrophes et des caractères interdits par des underscores
  s/\.+$//                                    # Suppression des points en fin de nom
  s/[[:space:]]*\.[[:space:]]*([^.]+)$/.\1/   # Suppression des espaces juste avant et / ou apres le dernier point
  s/^\.*$//                                   # Suppression des noms ne contenant que des points
  s/^(nul|prn|con|lpt[0-9]|com[0-9]|aux|COM¹|COM²|COM³|LPT¹|LPT²|LPT³)(\.|$)/\1_\2/I  # si nom exclu on ajoute le suffixe _
  s/^[[:space:]]*$/NONAME/' <<< "$filename")  # si espace ou vide => NONAME
  
  if test "$filename" != "$name_clean"; then
    suffix=0
    final_name="$directory/$name_clean"
    
    # eviter les doublons et renommer correctement quand meme :
    while test -e "$final_name"; do # Tant que le fichier cible existe déjà
      name="${name_clean##*/}"   # enlève le chemin
      base="$name"
      ext=""

      if [[ "$name" == .* ]]; then
        base="${name:1}"   # enlève le point initial
        if [[ "$base" == *.* ]]; then
          ext=".${base##*.}"
          base="${base%.*}"
        fi
      else
        if [[ "$name" == *.* ]]; then
          ext=".${name##*.}"
          base="${name%.*}"
        fi
      fi
      # Permet de renommer le tout ( les 4 possibilités ) , car $ext et $base sont definies au départ
      final_name="${directory}/${base}_${suffix}${ext}"

      ((suffix++))
    done
    
    echo " => '$1' serait renommé en '$final_name'"
    mv -v "$1"  "$final_name"
  fi
}

export -f sanitize

sanitize_dir() {
  Debut=$(date +%s);
  find "$1" -depth -exec bash -c 'sanitize "$0"' {} \;
  echo "le tout en $(($(date +%s)-Debut)) secondes."
}

sanitize_dir "$PWD"



le script samba rename , indique qu ' il n ' a pas pu renommer , mais il est 2 fois plus rapide :

#!/bin/bash

# Description des variables :
# $nomOriginal = nom complet rep ou fichier original
# $pathOriginal = chemin du repertoire original
# $nomModif = nom complet rep ou fichier modifié
# $pathModif = chemin du repertoire modifié
# $nomArgModif = nom dernier argument modifié
# FPNWE = chemin du fichier complet sans .ext = Full Path Name Without Extension
# $ext = extension du fichier le cas échéant sinon , renvoie le chemin complet du fichier.
# $fileNameWE = nom du fichier sans path , ni extension .

# --- Configuration ---
modif_activ=false  # true pour appliquer les modifications
execDir=""         # Chemin ABSOLU du dossier cible (vide = PWD)
#### FIN ####

# --- Variables globales ---
declare -i LongPath=0 NbNOTScanned=0 NbRepScanned=0 NbFileScanned=0 NbRepModified=0 NbFileModified=0 NbRepNOTModified=0 NbFileNOTModified=0; Debut=$(date +%s);
declare log_error="/tmp/error.log" log_modifs="/tmp/modifs"
### Liste des fichiers exclus
Exclus=( CON PRN AUX NUL NULL COM{0..9} LPT{0..9} COM¹ COM² COM³ LPT¹ LPT² LPT³ CLOCK$ )

# --- Initialisation ---
shopt -s globstar nullglob
echo "liste des erreurs ( fichiers ou dossiers ) n ' ayant pas pu etre modifiés :" > "$log_error"
echo "-------------------" > "$log_modifs"

# --- Fonctions ---
clean_complete_name() { # Nettoie un nom de fichier/dossier
    local name="$1"

    # Nettoyage des espaces (début, fin, autour des /, multiples)
    name=$(printf '%s' "$name" | sed -E '
    s/^[[:space:]]+//;
    s/[[:space:]]+$//;
    s/[[:space:]]*\/[[:space:]]*/\//g;
    s/[[:space:]]+/ /g
    s/[[:space:]]*\.[[:space:]]*([^.]+)$/.\1/   # Suppression des espaces juste avant et / ou apres le dernier point
    '| tr ''\''><"|?*\\:'  '_________')

    printf '%s\n' "$name"
}

for nomOriginal in "${execDir:=$PWD}"/**/*; do
    if test -L "$nomOriginal"; then
        ((NbNOTScanned++))
        continue
    elif test -f "$nomOriginal"; then
        ((NbFileScanned++))
        ext=${nomOriginal##*.} # get extension without filename
        if test "$nomOriginal" != "$ext"; then # si le fichier comporte une extension
            FPNWE="${nomOriginal%.*}" # get filename without extension
            FPNWE=$(clean_complete_name "$FPNWE")

            fileNameWE=${FPNWE##*/} # get only filename
            if [[ "${Exclus[*]}" ==  *" $fileNameWE "*  ]]; then FPNWE+="_"; fi

            ext=$(clean_complete_name "$ext")
            nomModif="$FPNWE.$ext"            
        else
            nomModif=$(clean_complete_name "$nomOriginal")
            nomArgModif=$(echo "$nomModif" | grep -o '[^/]*$') # Récupére le dernier argument
            if [[ "${Exclus[*]}" ==  *" $nomArgModif "*  ]]; then nomModif+="_"; fi # Vérifions si le nom n'est pas interdit.
        fi
    else
        ((NbRepScanned++))
        nomModif=$(clean_complete_name "$nomOriginal")
    fi

    if [[ "$nomOriginal" != "$nomModif" ]]; then # si il y a un changement a effectuer        
        nomArgModif=$(echo "$nomModif" | grep -o '[^/]*$') # Récupére le dernier argument
        
        # le nom du chemin ne doit pas dépasser 256 en standard , et chemin étendu 32767 max , prefixe windows = "\\?\" .
        #if (( "${#nomArgModif}" >= 256 || "${#nomModif}" >= 32767 )) ; then # Vérifions si la longueur n'est pas excessive
            if (( "${#nomModif}" >= 256 )) ; then # Vérifions si la longueur n'est pas excessive
                ((LongPath++))
                echo "Le nom de chemin de fichier est trop long ! impossible de renommer '$nomOriginal' en '$nomModif'" >> "$log_error"
            fi

            if test -d "$nomOriginal"; then # si c' est un dossier
                if test -e "$nomModif"; then # on verifie si il existe un dossier du meme nom avant de renommer
                    ((NbRepNOTModified++))
                    echo "$NbRepNOTModified un dossier du meme nom existe deja : impossible de renommer '$nomOriginal' en '$nomModif'" >> "$log_error"
                elif test ! -w "$(realpath "${nomOriginal}"/..)"; then # on verifie si le dossier parent est modifiable
                    ((NbRepNOTModified++))
                    echo "permission refusée : impossible de renommer '$nomOriginal' en '$nomModif'"
                    echo "$NbRepNOTModified permission refusée : impossible de renommer '$nomOriginal' en '$nomModif'" >> "$log_error"
                else # si pas de dossier du meme nom , on renomme
                    echo "dossier renommé : mkdir '$nomOriginal' ==> '$nomModif'"
                    if test "$modif_activ" = true; then
                        mkdir -p "$nomModif"
                        ((NbRepModified++))
                        echo "$NbRepModified CREER_REP : mkdir '$nomModif'" >> "$log_modifs"
                    fi
                fi
            elif test -f "$nomOriginal" ; then # si c est un fichier
                if test -e "$nomModif"; then # on verifie si il existe un fichier du meme nom avant de renommer et s ' il est modifiable
                    ((NbFileNOTModified++))
                    echo "$NbFileNOTModified un fichier du meme nom existe deja : impossible de renommer '$nomOriginal' en '$nomModif'" >> "$log_error"
                elif test ! -w "$(dirname "${nomOriginal}")"; then # on verifie si le dossier parent est modifiable
                    ((NbFileNOTModified++))
                    echo "permission refusée : impossible de renommer '$nomOriginal' en '$nomModif'"
                    echo "$NbFileNOTModified : permission refusée : impossible de renommer '$nomOriginal' en '$nomModif'" >> "$log_error"
                else # si pas de fichier du meme nom , on renomme
                    pathOriginal=${nomOriginal%/*} # chemin du repertoire original
                    pathModif=${nomModif%/*} # chemin apres modif
                    if [[ "$pathOriginal" != "$pathModif" ]]; then # si les chemins sont differents , c' est que l' arborescence a été modifiée :
                        nomModif="$pathModif"/"$nomArgModif" # dans ce cas on utilise l' arborescence modifiée precedemment + le nom modifié du dernier argument pour la destination
                    fi
                    echo "renommage du fichier : mv '$nomOriginal' ==> '$nomModif'"
                    if test "$modif_activ" = true; then
                        mv "$nomOriginal" "$nomModif"
                        NbFileModified+=1
                        echo "$NbFileModified RENOM : mv '$nomOriginal' en : '$nomModif'" >> "$log_modifs"
                    fi
                fi
            fi
        fi
    done

    # --- Affichage récapitulatif ---
    echo;
    echo "récapitulatif :"
    echo "$NbRepScanned dossiers et $NbFileScanned fichiers traités, $NbRepModified répertoires modifiés, $NbFileModified fichiers modifiés , le tout en $(($(date +%s)-Debut)) secondes."
    (( NbNOTScanned )) && echo "$NbNOTScanned non traités."
    echo;
    (( NbFileModified || NbRepModified )) && echo "liste des dossiers et fichiers modifiés dans '/tmp/modifs'"
    (( NbRepModified )) && echo "pour supprimer les dossiers vides , copiez collez la commande suivante : find '${execDir:=$PWD}' -type d -empty -delete"
    echo;
    if (( NbFileNOTModified || NbRepNOTModified || LongPath)); then
        echo "$NbFileNOTModified fichiers , $NbRepNOTModified répertoires n ' ayant pas pu etre modifiés"
        echo "vous avez $LongPath répertoires de taille trop importante."
        echo "liste des erreurs : cat '$log_error'"
        echo;
    fi

Dernière modification par iznobe (Le 24/04/2026, à 10:34)

Hors ligne

#112 Le 24/04/2026, à 11:47

iznobe

Re : [RESOLU] script mettre en conformité les noms de fichiers samba

Y a moyen certainement , de faire ça en plus " clair " :

          elif test -f "$nomOriginal" ; then # si c est un fichier
            if test ! -w "$(dirname "${nomOriginal}")"; then # on verifie si le dossier parent est modifiable
                ((NbFileNOTModified++))
                echo "permission refusée : impossible de renommer '$nomOriginal' en '$nomModif'"
                echo "$NbFileNOTModified : permission refusée : impossible de renommer '$nomOriginal' en '$nomModif'" >> "$log_error"
            else
                pathOriginal=${nomOriginal%/*} # chemin du repertoire original
                pathModif=${nomModif%/*} # chemin apres modif
                if [[ "$pathOriginal" != "$pathModif" ]]; then # si les chemins sont differents , c' est que l' arborescence a été modifiée :
                    nomModif="$pathModif"/"$nomArgModif" # dans ce cas on utilise l' arborescence modifiée precedemment + le nom modifié du dernier argument pour la destination
                fi
                
                # eviter les doublons et renommer correctement quand meme :
                directory="$(dirname "$nomModif")"
                name="${nomModif##*/}"  # enlève le chemin
                base="$name"
                declare -i suffix=0
                ext=""
                while test -e "$nomModif"; do # Tant que le fichier cible existe déjà
                  if [[ "$name" == .* ]]; then
                    base="${name:1}"   # enlève le point initial
                    if [[ "$base" == *.* ]]; then
                      ext=".${base##*.}"
                      base="${base%.*}"
                    fi
                  else
                    if [[ "$name" == *.* ]]; then
                      ext=".${name##*.}"
                      base="${name%.*}"
                    fi
                  fi
                  # Permet de renommer le tout ( les 4 possibilités ) , car $ext et $base sont definies au départ
                  nomModif="${directory}/${base}_${suffix}${ext}"
                  
                  ((suffix++))
                done
                
                echo "renommage du fichier : mv '$nomOriginal' ==> '$nomModif'"
                if test "$modif_activ" = true; then
                    mv "$nomOriginal" "$nomModif"
                    NbFileModified+=1
                    echo "$NbFileModified RENOM : mv '$nomOriginal' en : '$nomModif'" >> "$log_modifs"
                fi
            fi
        fi

?

Dernière modification par iznobe (Le 24/04/2026, à 11:47)

Hors ligne

#113 Le 27/04/2026, à 14:18

iznobe

Re : [RESOLU] script mettre en conformité les noms de fichiers samba

Bonjour , apres vérification , dans un script comme dans l ' autre , au niveau des " exclus " , ça ne fonctionne pas comme ça devrait .

En toute logique , avec  l' exclu suivant : " LPT " , que ce soit lpt , lPt , lPT , LPT , LpT , etc .... ils devraient tous être suffixés , ce qui n' est pas le cas actuellement .

Comment y remédier ?

Hors ligne

#114 Le 27/04/2026, à 14:47

iznobe

Re : [RESOLU] script mettre en conformité les noms de fichiers samba

#!/bin/bash

# Description des variables :
# $nomOriginal = nom complet rep ou fichier original
# $pathOriginal = chemin du repertoire original
# $nomModif = nom complet rep ou fichier modifié
# $pathModif = chemin du repertoire modifié
# $cleanFileName = nom fichier nettoyé
# FPNWE = chemin du fichier complet sans .ext = Full Path Name Without Extension
# $ext = extension du fichier le cas échéant sinon , renvoie le chemin complet du fichier.

# --- Configuration ---
modif_activ=false  # true pour appliquer les modifications
execDir=""         # Chemin ABSOLU du dossier cible (vide = PWD)
#### FIN ####

# --- Variables globales ---
declare -i LongPath=0 NbNOTScanned=0 NbRepScanned=0 NbFileScanned=0 NbRepModified=0 NbFileModified=0 NbRepNOTModified=0 NbFileNOTModified=0; Debut=$(date +%s);
declare log_error="/tmp/error.log" log_modifs="/tmp/modifs"
### Liste des fichiers exclus
#Exclus=( CON con PRN prn AUX aux NUL?L COM{0..9} com{0..9} LPT{0..9} lpt{0..9} COM¹ COM² COM³ com¹ com² com³ LPT¹ LPT² LPT³ lpt¹ lpt² lpt³ CLOCK$ clock$ )
Exclus=( CON PRN AUX NUL?L COM{0..9} LPT{0..9} COM¹ COM² COM³ LPT¹ LPT² LPT³ CLOCK$ )
# --- Initialisation ---
shopt -s globstar nullglob
echo "liste des erreurs ( fichiers ou dossiers ) n ' ayant pas pu etre modifiés :" > "$log_error"
echo "-------------------" > "$log_modifs"

clean_complete_name() { # Nettoie un nom de fichier/dossier
	local name="$1"

	# Nettoyage des espaces (début, fin, autour des /, multiples)
	name=$(printf '%s' "$name" | sed -E '
	s/^[[:space:]]+//;
	s/[[:space:]]+$//;
	s/[[:space:]]*\/[[:space:]]*/\//g;
	s/[[:space:]]+/ /g
	s/[[:space:]]*\.[[:space:]]*([^.]+)$/.\1/   # Suppression des espaces juste avant et / ou apres le dernier point
	'| tr ''\''><"|?*\\:'  '_________')

  if [[ " ${Exclus[*]} " == *" $(echo "${name##*/}" | tr '[:lower:]' '[:upper:]') "* ]]
    then name+="_";
  fi

	printf '%s\n' "$name"
}

for nomOriginal in "${execDir:=$PWD}"/**/*; do
	if test -L "$nomOriginal"; then
		((NbNOTScanned++))
		continue
	elif test -f "$nomOriginal"; then
		((NbFileScanned++))
		ext=${nomOriginal##*.} # get extension without filename
		if test "$nomOriginal" != "$ext"; then # si le fichier comporte une extension
			FPNWE="${nomOriginal%.*}" # get filename without extension
			FPNWE=$(clean_complete_name "$FPNWE")
      ext=$(clean_complete_name "$ext")
			nomModif="$FPNWE.$ext"
		else
			nomModif=$(clean_complete_name "$nomOriginal")
		fi
	else
		((NbRepScanned++))
		nomModif=$(clean_complete_name "$nomOriginal")
	fi

	if [[ "$nomOriginal" != "$nomModif" ]]; then # si il y a un changement a effectuer
		# le nom du chemin ne doit pas dépasser 256 en standard , et chemin étendu 32767 max , prefixe windows = "\\?\"
		if (( "${#nomModif}" >= 256 )) ; then # Vérifions si la longueur n'est pas excessive
			((LongPath++))
			echo "Le nom de chemin de fichier est trop long ! impossible de renommer '$nomOriginal' en '$nomModif'" >> "$log_error"
		fi

		if test -d "$nomOriginal"; then # si c' est un dossier
			if test ! -w "$(realpath "${nomOriginal}"/..)"; then # on verifie si le dossier parent est modifiable
				((NbRepNOTModified++))
				echo "permission refusée : impossible de renommer '$nomOriginal' en '$nomModif'"
				echo "$NbRepNOTModified permission refusée : impossible de renommer '$nomOriginal' en '$nomModif'" >> "$log_error"
			else # eviter les doublons et renommer correctement quand meme :
				suffix=0
				while test -e "$nomModif"; do # Tant que le dossier cible existe déjà
					nomModif="${nomModif}_${suffix}"
					((suffix++))
				done

				echo "dossier renommé : mkdir '$nomOriginal' ==> '$nomModif'"
				if test "$modif_activ" = true; then
					mkdir -pv "$nomModif"
					((NbRepModified++))
					echo "$NbRepModified CREER_REP : mkdir '$nomModif'" >> "$log_modifs"
				fi
			fi
		elif test -f "$nomOriginal" ; then # si c est un fichier
			if test ! -w "$(dirname "${nomOriginal}")"; then # on verifie si le dossier parent est modifiable
				((NbFileNOTModified++))
				echo "permission refusée : impossible de renommer '$nomOriginal' en '$nomModif'"
				echo "$NbFileNOTModified : permission refusée : impossible de renommer '$nomOriginal' en '$nomModif'" >> "$log_error"
			else
				pathOriginal=${nomOriginal%/*} # chemin du repertoire original
				pathModif=${nomModif%/*} # chemin apres modif
				if [[ "$pathOriginal" != "$pathModif" ]]; then # si les chemins sont differents , c' est que l' arborescence a été modifiée :
					nomModif="$pathModif"/"${nomModif##*/}" # dans ce cas on utilise l' arborescence modifiée precedemment + le nom modifié du dernier argument pour la destination
				fi

				# eviter les doublons et renommer correctement quand meme :
				directory="${nomModif%/*}"
        cleanFileName="${nomModif##*/}"
        base="$cleanFileName"
        ext=""
        suffix=0

        if [[ "$cleanFileName" == .* ]]; then
            base="${cleanFileName:1}" # Fichier caché (ex: .bash_profile) , Enlève le point initial
            if [[ "$base" == *.* ]]; then
                ext=".${base##*.}"
                base="${base%.*}"
            fi
        else
            if [[ "$cleanFileName" == *.* ]]; then # Fichier normal (ex: fichier.txt)
                ext=".${cleanFileName##*.}"
                base="${cleanFileName%.*}"
            fi
        fi

        while [[ -e "$nomModif" ]]; do
            nomModif="${directory}/${base}_${suffix}${ext}"
            ((suffix++))
        done

				echo "renommage du fichier : mv '$nomOriginal' ==> '$nomModif'"
				if test "$modif_activ" = true; then
					mv  "$nomOriginal" "$nomModif"
					NbFileModified+=1
					echo "$NbFileModified RENOM : mv '$nomOriginal' en : '$nomModif'" >> "$log_modifs"
				fi
			fi
		fi
	fi
done

echo;
echo "récapitulatif :"
echo "$NbRepScanned dossiers et $NbFileScanned fichiers traités, $NbRepModified répertoires modifiés, $NbFileModified fichiers modifiés , le tout en $(($(date +%s)-Debut)) secondes."
(( NbNOTScanned )) && echo "$NbNOTScanned non traités."
echo;
(( NbFileModified || NbRepModified )) && echo "Pour voir les modifications : cat '/tmp/modifs'"
(( NbRepModified )) && echo "pour supprimer les dossiers vides , copiez collez la commande suivante : find '${execDir:=$PWD}' -type d -empty -delete"
echo;
if (( NbFileNOTModified || NbRepNOTModified || LongPath)); then
	echo "$NbFileNOTModified fichiers , $NbRepNOTModified répertoires n ' ayant pas pu etre modifiés"
	echo "vous avez $LongPath répertoires de taille trop importante."
	echo "liste des erreurs : cat '$log_error'"
	echo;
fi

Optimisation + correction pour les noms exclus apportée.

Dernière modification par iznobe (Le 27/04/2026, à 17:31)

Hors ligne

#115 Le 27/04/2026, à 21:55

iznobe

Re : [RESOLU] script mettre en conformité les noms de fichiers samba

encore plus optimisé et traite plus de cas :

check_exclu() {
	local name="$1"
	if [[ " ${Exclus[*]} " == *" $(echo "${name##*/}" | tr '[:lower:]' '[:upper:]') "* ]]; then name+="_"; fi
	printf '%s\n' "$name"
}

clean_name() { # Nettoie un nom de fichier/dossier
  printf '%s' "$1" | sed -E '
    s/^[[:space:]]+|[[:space:]]+$//g;
    s/[[:space:]]*\/[[:space:]]*/\//g;
    s/[[:space:]]+/ /g;
    s/[[:space:]]*\.[[:space:]]*([^.]+)$/.\1/;
    s/[^[:print:]]|['\''><"|?*\\:]/_/g
    '
}

Dernière modification par iznobe (Le 27/04/2026, à 22:10)

Hors ligne

#116 Le 27/04/2026, à 23:59

Watael

Re : [RESOLU] script mettre en conformité les noms de fichiers samba

pas besoin de tr :

local name=${1^^}

Connected \o/
Welcome to sHell. · eval is evil.

En ligne

#117 Le 28/04/2026, à 02:08

MicP

Re : [RESOLU] script mettre en conformité les noms de fichiers samba

Bonjour

Une formulation plus courte de la ligne suivante :

Exclus=( CON PRN AUX NUL?L COM{0..9} LPT{0..9} COM¹ COM² COM³ LPT¹ LPT² LPT³ CLOCK$ )

qui pourrait aussi s'écrire comme ça :

Exclus=( CON PRN AUX NUL?L {COM,LPT}{{0..9},¹,²,³} CLOCK$ )

Hors ligne

#118 Le 28/04/2026, à 05:16

Watael

Re : [RESOLU] script mettre en conformité les noms de fichiers samba

j'ai un gros doute sur NUL?L.


Connected \o/
Welcome to sHell. · eval is evil.

En ligne

#119 Le 28/04/2026, à 05:44

MicP

Re : [RESOLU] script mettre en conformité les noms de fichiers samba

Effectivement, ça m'a fait aussi tiquer, mais je n'ai pas vraiment pris le temps de lire tout le script pour voir ce qui est fait avec ce NUL?L
Alors j'ai laissé tel quel.

Hors ligne

#120 Le 28/04/2026, à 07:53

iznobe

Re : [RESOLU] script mettre en conformité les noms de fichiers samba

Bonjour , oui ,  finalement j ' ai changé aussi big_smile n ' étant pas certain du truc a 100 % , de toute maniere , que ce soit avec " NUL?L " ou " NUL NULL " , ça ne fonctionne pas quand meme hmm.


le script a l ' heure d' aujourd hui :

#!/bin/bash

# Description des variables :
# $nomOriginal = nom complet rep ou fichier original
# $pathOriginal = chemin du repertoire original
# $nomModif = nom complet rep ou fichier modifié
# $pathModif = chemin du repertoire modifié
# $cleanFileName = nom fichier nettoyé
# FPNWE = chemin du fichier complet sans .ext = Full Path Name Without Extension
# $ext = extension du fichier le cas échéant sinon , renvoie le chemin complet du fichier.

# --- Configuration ---
modif_activ=false  # true pour appliquer les modifications
execDir=""         # Chemin ABSOLU du dossier cible (vide = PWD)
#### FIN ####

# --- Variables globales ---
declare -i count=0 LongPath=0 NbNOTScanned=0 NbRepScanned=0 NbFileScanned=0 NbRepModified=0 NbFileModified=0 NbRepNOTModified=0 NbFileNOTModified=0; Debut=$(date +%s);
declare log_error="/tmp/error.log" log_modifs="/tmp/modifs"
### Liste des fichiers exclus
Exclus=( CON PRN AUX NUL NULL COM{0..9} LPT{0..9} COM¹ COM² COM³ LPT¹ LPT² LPT³ CLOCK$ )
# --- Initialisation ---
shopt -s globstar nullglob
echo "liste des erreurs ( fichiers ou dossiers ) n ' ayant pas pu etre modifiés :" > "$log_error"
echo "-------------------" > "$log_modifs"

check_exclu() {
	local name="$1"
	if [[ " ${Exclus[*]} " == *" ${name^^{name##*/}} "* ]]; then name+="_"; fi
	printf '%s\n' "$name"
}

clean_name() { # Nettoie un nom de fichier/dossier
  printf '%s' "$1" | sed -E '
    s/^[[:space:]]+|[[:space:]]+$//g;
    s/[[:space:]]*\/[[:space:]]*/\//g;
    s/[[:space:]]+/ /g;
    s/[[:space:]]*\.[[:space:]]*([^.]+)$/.\1/;
    s/[^[:print:]]|['\''><"|?*\\:]/_/g
    #s/[^[:print:]]|[\/'\''><"|?*\\:]/_/g
    '
}

for nomOriginal in "${execDir:=$PWD}"/**/*; do
	if test -L "$nomOriginal"; then
		((NbNOTScanned++))
		continue
	elif test -f "$nomOriginal"; then
		((NbFileScanned++))
		ext=${nomOriginal##*.} # get extension without filename
		if test "$nomOriginal" != "$ext"; then # si le fichier comporte une extension
			FPNWE="${nomOriginal%.*}" # get filename without extension
			FPNWE=$(clean_name "$FPNWE")
			FPNWE=$(check_exclu "$FPNWE")

			ext=$(clean_name "$ext")
			nomModif="$FPNWE.$ext"
		else # si le fichier ne comporte pas d ' extension
			nomModif=$(clean_name "$nomOriginal")
			nomModif=$(check_exclu "$nomModif")
		fi
	else
		((NbRepScanned++))
		nomModif=$(clean_name "$nomOriginal")
		nomModif=$(check_exclu "$nomModif")
	fi

	if [[ "$nomOriginal" != "$nomModif" ]]; then # si il y a un changement a effectuer
		((count++))
		# le nom du chemin ne doit pas dépasser 256 en standard , et chemin étendu 32767 max , prefixe windows = "\\?\"
		if (( "${#nomModif}" >= 256 )) ; then # Vérifions si la longueur n'est pas excessive
			((LongPath++))
			echo "Le nom de chemin de fichier est trop long ! impossible de renommer '$nomOriginal' en '$nomModif'" >> "$log_error"
		fi

		if test -d "$nomOriginal"; then # si c' est un dossier
			if test ! -w "$(realpath "${nomOriginal}"/..)"; then # on verifie si le dossier parent est modifiable
				((NbRepNOTModified++))
				echo "permission refusée : impossible de renommer '$nomOriginal' en '$nomModif'"
				echo "$NbRepNOTModified permission refusée : impossible de renommer '$nomOriginal' en '$nomModif'" >> "$log_error"
			else # eviter les doublons et renommer correctement quand meme :

				suffix=0
				while test -e "$nomModif"; do # Tant que le dossier cible existe déjà
					nomModif="${nomModif}_${suffix}"
					((suffix++))
				done

				echo "dossier renommé : mkdir '$nomOriginal' ==> '$nomModif'"
				if test "$modif_activ" = true; then
					mkdir -pv "$nomModif"
					((NbRepModified++))
					echo "$NbRepModified CREER_REP : mkdir '$nomModif'" >> "$log_modifs"
				fi
			fi
		elif test -f "$nomOriginal" ; then # si c est un fichier
			if test ! -w "$(dirname "${nomOriginal}")"; then # on verifie si le dossier parent est modifiable
				((NbFileNOTModified++))
				echo "permission refusée : impossible de renommer '$nomOriginal' en '$nomModif'"
				echo "$NbFileNOTModified : permission refusée : impossible de renommer '$nomOriginal' en '$nomModif'" >> "$log_error"
			else
				pathOriginal=${nomOriginal%/*} # chemin du repertoire original
				pathModif=${nomModif%/*} # chemin apres modif
				if [[ "$pathOriginal" != "$pathModif" ]]; then # si les chemins sont differents , c' est que l' arborescence a été modifiée :
					nomModif="$pathModif"/"${nomModif##*/}" # dans ce cas on utilise l' arborescence modifiée precedemment + le nom modifié du dernier argument pour la destination
				fi

				# eviter les doublons et renommer correctement quand meme :
				directory="${nomModif%/*}"
				cleanFileName="${nomModif##*/}"
				base="$cleanFileName"
				ext=""
				suffix=0

				if [[ "$cleanFileName" == .* ]]; then
					base="${cleanFileName:1}" # Fichier caché (ex: .bash_profile) , Enlève le point initial
					if [[ "$base" == *.* ]]; then
						ext=".${base##*.}"
						base="${base%.*}"
					fi
				else
					if [[ "$cleanFileName" == *.* ]]; then # Fichier normal (ex: fichier.txt)
						ext=".${cleanFileName##*.}"
						base="${cleanFileName%.*}"
					fi
				fi

				while [[ -e "$nomModif" ]]; do
					nomModif="${directory}/${base}_${suffix}${ext}"
					((suffix++))
				done

				echo "renommage du fichier : mv '$nomOriginal' ==> '$nomModif'"
				if test "$modif_activ" = true; then
					mv  "$nomOriginal" "$nomModif"
					NbFileModified+=1
					echo "$NbFileModified RENOM : mv '$nomOriginal' en : '$nomModif'" >> "$log_modifs"
				fi
			fi
		fi
	fi
done

echo;
echo "récapitulatif : modif count = $count"
echo "$NbRepScanned dossiers et $NbFileScanned fichiers traités, $NbRepModified répertoires modifiés, $NbFileModified fichiers modifiés , le tout en $(($(date +%s)-Debut)) secondes."
(( NbNOTScanned )) && echo "$NbNOTScanned non traités."
echo;
(( NbFileModified || NbRepModified )) && echo "Pour voir les modifications : cat '/tmp/modifs'"
(( NbRepModified )) && echo "pour supprimer les dossiers vides , copiez collez la commande suivante : find '${execDir:=$PWD}' -type d -empty -delete"
echo;
if (( NbFileNOTModified || NbRepNOTModified || LongPath)); then
	echo "$NbFileNOTModified fichiers , $NbRepNOTModified répertoires n ' ayant pas pu etre modifiés"
	echo "vous avez $LongPath répertoires de taille trop importante."
	echo "liste des erreurs : cat '$log_error'"
	echo;
fi

j ' ai pris le temps optimiser le script santize  , avec un seul awk , c ' est beaucoup mieux que 10 sed tongue .
Aussi en passant des paramètres " pur bash " , c ' est beaucoup mieux .
Cependant il subsiste une erreur entre les 2  que je n' arrive pas ni a trouver ni a corriger .
il semblerait que dans le samba rename , les espaces autour de tous les " / " soient gérés , et que ce n' est pas le cas dans le sanitize .
Toujours est il que dans certains cas , certain fichiers sont modifiés par le script samba_rename ( au dessus ) , et pas par le sanitize :

#!/bin/bash

sanitize() {
  shopt -s extglob

  filename=${1##*/}
  directory=${1%/*}

  name_clean=$(
  printf '%s' "$filename" |
  awk '
  BEGIN {
    IGNORECASE = 1

    reserved["nul"]; reserved["prn"]; reserved["con"]; reserved["aux"]
    for (i=0;i<=9;i++) { reserved["com" i]; reserved["lpt" i] }
    reserved["com¹"]; reserved["com²"]; reserved["com³"]
    reserved["lpt¹"]; reserved["lpt²"]; reserved["lpt³"]
  }
  {
    # trim
    gsub(/^[[:space:]]+|[[:space:]]+$/, "")

    # espaces autour /
    gsub(/[[:space:]]*\/[[:space:]]*/, "/")

    # espaces multiples
    gsub(/[[:space:]]+/, " ")

    # caractères interdits + contrôle
    gsub(/['"'"'\\/:\*\?\"<>\|\001-\037\177]/, "_")

    # suppression points finaux
    sub(/\.+$/, "")

    # nettoyage dernier point
    if (match($0, /[[:space:]]*\.[[:space:]]*([^.]+)$/)) {
      ext = substr($0, RSTART, RLENGTH)
      sub(/^[[:space:]]*\.[[:space:]]*/, ".", ext)
      $0 = substr($0, 1, RSTART-1) ext
    }

    # uniquement des points → vide
    if ($0 ~ /^\.*$/) $0=""

    # basename sans extension
    base = $0
    sub(/\..*$/, "", base)

    if (tolower(base) in reserved) {
      $0 = base "_" substr($0, length(base)+1)
    }

    # vide → NONAME
    if ($0 ~ /^[[:space:]]*$/) $0="NONAME"

    print
  }'
)

  if test "$filename" != "$name_clean"; then
    suffix=0
    final_name="$directory/$name_clean"

    name="${name_clean##*/}"
    base="$name"
    ext=""

    if [[ "$name" == .* ]]; then
      base="${name:1}"
      if [[ "$base" == *.* ]]; then
        ext="${base##*.}"
        base="${base%.*}"
      fi
    else
      if [[ "$name" == *.* ]]; then
        ext="${name##*.}"
        base="${name%.*}"
      fi
    fi

    while test -e "$final_name"; do
      final_name="${directory}/${base}_${suffix}${ext}"
      ((suffix++))
    done

    echo " => '$1' serait renommé en '$final_name'"
    #mv -v "$1" "$final_name" >> /tmp/sanitize.log
  fi
}
export -f sanitize

sanitize_dir() {
  Debut=$(date +%s);
  find "$1" -depth -exec bash -c 'sanitize "$0"' {} \;
  echo "le tout en $(($(date +%s)-Debut)) secondes."
}

sanitize_dir "$PWD"


Un nom a problème par exemple :  ' test . pour . fun . ext '

Dernière modification par iznobe (Le 28/04/2026, à 08:20)

Hors ligne

#121 Le 28/04/2026, à 08:27

iznobe

Re : [RESOLU] script mettre en conformité les noms de fichiers samba

Watael a écrit :

pas besoin de tr :

local name=${1^^}

En fait , j ' ai pas trouvé comment faire un truc propre .
ça fonctionne :

check_exclu() {
  local name="$1"
  if [[ " ${Exclus[*]} " == *" $(echo "${name##*/}" | tr '[:lower:]' '[:upper:]') "* ]]; then name+="_"; fi
  printf '%s\n' "$name"
}

les autres trucs avec " ^^  " , pas .

obtenu lorsque ça fonctionne :

iznobe@iznobe-PC-U26:~/Scripts/test$ bash ~/Scripts/rename.sh 
dossier renommé : mkdir '/home/iznobe/Scripts/test/com¹' ==> '/home/iznobe/Scripts/test/com¹_'
renommage du fichier : mv '/home/iznobe/Scripts/test/con' ==> '/home/iznobe/Scripts/test/con_'
renommage du fichier : mv '/home/iznobe/Scripts/test/CoN' ==> '/home/iznobe/Scripts/test/CoN_'
renommage du fichier : mv '/home/iznobe/Scripts/test/lpt2' ==> '/home/iznobe/Scripts/test/lpt2_'
renommage du fichier : mv '/home/iznobe/Scripts/test/lpt²' ==> '/home/iznobe/Scripts/test/lpt²_'
renommage du fichier : mv '/home/iznobe/Scripts/test/LPT3' ==> '/home/iznobe/Scripts/test/LPT3_'
renommage du fichier : mv '/home/iznobe/Scripts/test/nul' ==> '/home/iznobe/Scripts/test/nul_'
renommage du fichier : mv '/home/iznobe/Scripts/test/nUl' ==> '/home/iznobe/Scripts/test/nUl_'
renommage du fichier : mv '/home/iznobe/Scripts/test/NuLl' ==> '/home/iznobe/Scripts/test/NuLl_'
renommage du fichier : mv '/home/iznobe/Scripts/test/prn' ==> '/home/iznobe/Scripts/test/prn_'
renommage du fichier : mv '/home/iznobe/Scripts/test/     PrN .   txt  ' ==> '/home/iznobe/Scripts/test/PrN_.txt'
renommage du fichier : mv '/home/iznobe/Scripts/test/ test . pour . fun . ext ' ==> '/home/iznobe/Scripts/test/test . pour.fun.ext'
renommage du fichier : mv '/home/iznobe/Scripts/test/ v  etrtrsde  .  point  ' ==> '/home/iznobe/Scripts/test/v etrtrsde.point'

récapitulatif : modif count = 13
1 dossiers et 14 fichiers traités, 0 répertoires modifiés, 0 fichiers modifiés , le tout en 0 secondes.
iznobe@iznobe-PC-U26:~/Scripts/test$ 

un des trucs tester qui ne fonctionne pas :

.
check_exclu() {
  local name="$1"
  if [[ " ${Exclus[*]} " == *" ${name##*/^^} "* ]]; then name+="_"; fi
  printf '%s\n' "$name"
}

un autre :

check_exclu() {
	local name="$1"
	if [[ " ${Exclus[*]} " == *" ${name^^{name##*/}} "* ]]; then name+="_"; fi
	printf '%s\n' "$name"
}

Encore un :

check_exclu() {
  local name="$1"
  if [[ " ${Exclus[*]} " == *" ${name^^"${name##*/}"} "* ]]; then name+="_"; fi
  printf '%s\n' "$name"
}

Dans les autres cas , j ' ai obtenu :

iznobe@iznobe-PC-U26:~/Scripts/test$ bash ~/Scripts/rename.sh 
renommage du fichier : mv '/home/iznobe/Scripts/test/     PrN .   txt  ' ==> '/home/iznobe/Scripts/test/PrN.txt'
renommage du fichier : mv '/home/iznobe/Scripts/test/ test . pour . fun . ext ' ==> '/home/iznobe/Scripts/test/test . pour.fun.ext'
renommage du fichier : mv '/home/iznobe/Scripts/test/ v  etrtrsde  .  point  ' ==> '/home/iznobe/Scripts/test/v etrtrsde.point'

récapitulatif : modif count = 3
1 dossiers et 14 fichiers traités, 0 répertoires modifiés, 0 fichiers modifiés , le tout en 0 secondes.
iznobe@iznobe-PC-U26:~/Scripts/test$ 

et si je "sors" de la condition :

check_exclu() {
  local name="$1"
  name="${name^^}"
  if [[ " ${Exclus[*]} " == *" $(echo "${name##*/}") "* ]]; then name+="_"; fi
  printf '%s\n' "$name"
}

alors tous les noms sont renommés en majuscules roll :

iznobe@iznobe-PC-U26:~/Scripts/test$ bash ~/Scripts/rename.sh 
dossier renommé : mkdir '/home/iznobe/Scripts/test/com¹' ==> '/HOME/IZNOBE/SCRIPTS/TEST/COM¹_'
renommage du fichier : mv '/home/iznobe/Scripts/test/com 2' ==> '/HOME/IZNOBE/SCRIPTS/TEST/COM 2'
renommage du fichier : mv '/home/iznobe/Scripts/test/con' ==> '/HOME/IZNOBE/SCRIPTS/TEST/CON_'
renommage du fichier : mv '/home/iznobe/Scripts/test/CoN' ==> '/HOME/IZNOBE/SCRIPTS/TEST/CON_'
renommage du fichier : mv '/home/iznobe/Scripts/test/lpt2' ==> '/HOME/IZNOBE/SCRIPTS/TEST/LPT2_'
renommage du fichier : mv '/home/iznobe/Scripts/test/lpt²' ==> '/HOME/IZNOBE/SCRIPTS/TEST/LPT²_'
renommage du fichier : mv '/home/iznobe/Scripts/test/LPT3' ==> '/HOME/IZNOBE/SCRIPTS/TEST/LPT3_'
renommage du fichier : mv '/home/iznobe/Scripts/test/nul' ==> '/HOME/IZNOBE/SCRIPTS/TEST/NUL_'
renommage du fichier : mv '/home/iznobe/Scripts/test/nUl' ==> '/HOME/IZNOBE/SCRIPTS/TEST/NUL_'
renommage du fichier : mv '/home/iznobe/Scripts/test/NuLl' ==> '/HOME/IZNOBE/SCRIPTS/TEST/NULL_'
renommage du fichier : mv '/home/iznobe/Scripts/test/pecon12' ==> '/HOME/IZNOBE/SCRIPTS/TEST/PECON12'
renommage du fichier : mv '/home/iznobe/Scripts/test/prn' ==> '/HOME/IZNOBE/SCRIPTS/TEST/PRN_'
renommage du fichier : mv '/home/iznobe/Scripts/test/     PrN .   txt  ' ==> '/HOME/IZNOBE/SCRIPTS/TEST/PRN_.txt'
renommage du fichier : mv '/home/iznobe/Scripts/test/ test . pour . fun . ext ' ==> '/HOME/IZNOBE/SCRIPTS/TEST/TEST . POUR.FUN.ext'
renommage du fichier : mv '/home/iznobe/Scripts/test/ v  etrtrsde  .  point  ' ==> '/HOME/IZNOBE/SCRIPTS/TEST/V ETRTRSDE.point'

récapitulatif : modif count = 15
1 dossiers et 14 fichiers traités, 0 répertoires modifiés, 0 fichiers modifiés , le tout en 0 secondes.

Dernière modification par iznobe (Le 28/04/2026, à 12:44)

Hors ligne

#122 Le 28/04/2026, à 12:54

Watael

Re : [RESOLU] script mettre en conformité les noms de fichiers samba

split le chemin et le nom.

checkExclu() {
    local name=${1##*/} path=${1%/*}
    if [[ " ${Exclus[*]} " == *" ${name^^}"* ]]; then name+="_"; fi
    echo "$path/$name"
}

Edit: correction inversion path <-> name

Dernière modification par Watael (Le 28/04/2026, à 15:28)


Connected \o/
Welcome to sHell. · eval is evil.

En ligne

#123 Le 28/04/2026, à 13:38

iznobe

Re : [RESOLU] script mettre en conformité les noms de fichiers samba

bon finalement avec , :

check_exclu() {
	local name="$1"
	local base="${name##*/}"

	if [[ " ${Exclus[*]} " == *" ${base^^} "* ]]; then name+="_"; fi

	printf '%s\n' "$name"
}

ça passe .


@Watael , avec ta version , j ' obtenais :

iznobe@iznobe-PC-U26:~/Scripts/test$ bash ~/Scripts/rename.sh 
dossier renommé : mkdir '/home/iznobe/Scripts/test/com¹' ==> 'com¹//home/iznobe/Scripts/test'
renommage du fichier : mv '/home/iznobe/Scripts/test/com 2' ==> 'com 2//home/iznobe/Scripts/test'
renommage du fichier : mv '/home/iznobe/Scripts/test/con' ==> 'con//home/iznobe/Scripts/test'
renommage du fichier : mv '/home/iznobe/Scripts/test/CoN' ==> 'CoN//home/iznobe/Scripts/test'
renommage du fichier : mv '/home/iznobe/Scripts/test/lpt2' ==> 'lpt2//home/iznobe/Scripts/test'
renommage du fichier : mv '/home/iznobe/Scripts/test/lpt²' ==> 'lpt²//home/iznobe/Scripts/test'
renommage du fichier : mv '/home/iznobe/Scripts/test/LPT3' ==> 'LPT3//home/iznobe/Scripts/test'
renommage du fichier : mv '/home/iznobe/Scripts/test/nul' ==> 'nul//home/iznobe/Scripts/test'
renommage du fichier : mv '/home/iznobe/Scripts/test/nUl' ==> 'nUl//home/iznobe/Scripts/test'
renommage du fichier : mv '/home/iznobe/Scripts/test/NuLl' ==> 'NuLl//home/iznobe/Scripts/test'
renommage du fichier : mv '/home/iznobe/Scripts/test/pecon12' ==> 'pecon12//home/iznobe/Scripts/test'
renommage du fichier : mv '/home/iznobe/Scripts/test/prn' ==> 'prn//home/iznobe/Scripts/test'
renommage du fichier : mv '/home/iznobe/Scripts/test/     PrN .   txt  ' ==> 'PrN.txt/PrN.txt'
renommage du fichier : mv '/home/iznobe/Scripts/test/ test . pour . fun . ext ' ==> 'test . pour . fun.ext/test . pour . fun.ext'
renommage du fichier : mv '/home/iznobe/Scripts/test/ v  etrtrsde  .  point  ' ==> 'v etrtrsde.point/v etrtrsde.point'

récapitulatif : modif count = 15
1 dossiers et 14 fichiers traités, 0 répertoires modifiés, 0 fichiers modifiés , le tout en 0 secondes.

Mais ça m ' a mis sur la bonne voie wink

j ' ai remplacé dans la fonctions tous les sed par le awk .
j ' ai changé la logique de correction des fichiers avec extensions :

elif test -f "$nomOriginal"; then
		((NbFileScanned++))
		ext=${nomOriginal##*.} # get extension without filename
		if test "$nomOriginal" != "$ext"; then # si le fichier comporte une extension
			FP=$(clean_name "$nomOriginal")
			FP=$(check_exclu "$FP")

			FPNWE=${FP%.*} # get filename without extension

			ext=$(clean_name "$ext")
			nomModif="$FPNWE.$ext"

car c' est elle qui induisait le bug des espaces devant les points , en déplaçant le dernier point ....
et là on commence a avoir quelquechose de vraiment pas mal ( scanne en 3 fois plus rapide que le sanitize.sh ! ) avec exactement les même résultats , les logs et les comptes en prime big_smile  :

#!/bin/bash

# Description des variables :
# $nomOriginal = nom complet rep ou fichier original
# $pathOriginal = chemin du repertoire original
# $nomModif = nom complet rep ou fichier modifié
# $pathModif = chemin du repertoire modifié
# $cleanFileName = nom fichier nettoyé
# FPNWE = chemin du fichier complet sans .ext = Full Path Name Without Extension
# $ext = extension du fichier le cas échéant sinon , renvoie le chemin complet du fichier.

# --- Configuration ---
modif_activ=false  # true pour appliquer les modifications
execDir=""         # Chemin ABSOLU du dossier cible (vide = PWD)
#### FIN ####

# --- Variables globales ---
declare -i count=0 LongPath=0 NbNOTScanned=0 NbRepScanned=0 NbFileScanned=0 NbRepModified=0 NbFileModified=0 NbRepNOTModified=0 NbFileNOTModified=0; Debut=$(date +%s);
declare log_error="/tmp/error.log" log_modifs="/tmp/modifs"
### Liste des fichiers exclus
Exclus=( CON PRN AUX NUL NULL COM{0..9} LPT{0..9} COM¹ COM² COM³ LPT¹ LPT² LPT³ CLOCK$ )
# --- Initialisation ---
shopt -s globstar nullglob
echo "liste des erreurs ( fichiers ou dossiers ) n ' ayant pas pu etre modifiés :" > "$log_error"
echo "-------------------" > "$log_modifs"

check_exclu() {
	local name="$1"
	local base="${name##*/}"

	if [[ " ${Exclus[*]} " == *" ${base^^} "* ]]; then name+="_"; fi

	printf '%s\n' "$name"
}

clean_name() { # Nettoie un nom de fichier/dossier
	printf '%s' "$1" | awk '
	BEGIN {
		IGNORECASE = 1

		reserved["nul"]; reserved["prn"]; reserved["con"]; reserved["aux"]
		for (i=0;i<=9;i++) { reserved["com" i]; reserved["lpt" i] }
		reserved["com¹"]; reserved["com²"]; reserved["com³"]
		reserved["lpt¹"]; reserved["lpt²"]; reserved["lpt³"]
	}
	{
		# trim
		gsub(/^[[:space:]]+|[[:space:]]+$/, "")

		# espaces autour /
		gsub(/[[:space:]]*\/[[:space:]]*/, "/")

		# espaces multiples
		gsub(/[[:space:]]+/, " ")

		# caractères interdits + contrôle
		gsub(/['"'"'\\:\*\?\"<>\|\001-\037\177]/, "_")

		# suppression points finaux
		sub(/\.+$/, "")

		# nettoyage dernier point
		if (match($0, /[[:space:]]*\.[[:space:]]*([^.]+)$/)) {
			ext = substr($0, RSTART, RLENGTH)
			sub(/^[[:space:]]*\.[[:space:]]*/, ".", ext)
			$0 = substr($0, 1, RSTART-1) ext
		}

		# uniquement des points → vide
		if ($0 ~ /^\.*$/) $0=""

			# basename sans extension
			base = $0
			sub(/\..*$/, "", base)

			if (tolower(base) in reserved) {
				$0 = base "_" substr($0, length(base)+1)
			}

			# vide → NONAME
			if ($0 ~ /^[[:space:]]*$/) $0="NONAME"

				print
			}'
		}

for nomOriginal in "${execDir:=$PWD}"/**/*; do
	if test -L "$nomOriginal"; then
		((NbNOTScanned++))
		continue
	elif test -f "$nomOriginal"; then
		((NbFileScanned++))
		ext=${nomOriginal##*.} # get extension without filename
		if test "$nomOriginal" != "$ext"; then # si le fichier comporte une extension
			FP=$(clean_name "$nomOriginal")
			FP=$(check_exclu "$FP")

			FPNWE=${FP%.*} # get filename without extension

			ext=$(clean_name "$ext")
			nomModif="$FPNWE.$ext"
		else # si le fichier ne comporte pas d ' extension
			nomModif=$(clean_name "$nomOriginal")
			nomModif=$(check_exclu "$nomModif")
		fi
	else
		((NbRepScanned++))
		nomModif=$(clean_name "$nomOriginal")
		nomModif=$(check_exclu "$nomModif")
	fi

	if [[ "$nomOriginal" != "$nomModif" ]]; then # si il y a un changement a effectuer
		((count++))
		# le nom du chemin ne doit pas dépasser 256 en standard , et chemin étendu 32767 max , prefixe windows = "\\?\"
		if (( "${#nomModif}" >= 256 )) ; then # Vérifions si la longueur n'est pas excessive
			((LongPath++))
			echo "Le nom de chemin de fichier est trop long ! impossible de renommer '$nomOriginal' en '$nomModif'" >> "$log_error"
		fi

		if test -d "$nomOriginal"; then # si c' est un dossier
			if test ! -w "$(realpath "${nomOriginal}"/..)"; then # on verifie si le dossier parent est modifiable
				((NbRepNOTModified++))
				echo "permission refusée : impossible de renommer '$nomOriginal' en '$nomModif'"
				echo "$NbRepNOTModified permission refusée : impossible de renommer '$nomOriginal' en '$nomModif'" >> "$log_error"
			else # eviter les doublons et renommer correctement quand meme :

				suffix=0
				while test -e "$nomModif"; do # Tant que le dossier cible existe déjà
					nomModif="${nomModif}_${suffix}"
					((suffix++))
				done

				echo "dossier renommé : mkdir '$nomOriginal' ==> '$nomModif'"
				if test "$modif_activ" = true; then
					mkdir -pv "$nomModif"
					((NbRepModified++))
					echo "$NbRepModified CREER_REP : mkdir '$nomModif'" >> "$log_modifs"
				fi
			fi
		elif test -f "$nomOriginal" ; then # si c est un fichier
			if test ! -w "$(dirname "${nomOriginal}")"; then # on verifie si le dossier parent est modifiable
				((NbFileNOTModified++))
				echo "permission refusée : impossible de renommer '$nomOriginal' en '$nomModif'"
				echo "$NbFileNOTModified : permission refusée : impossible de renommer '$nomOriginal' en '$nomModif'" >> "$log_error"
			else
				pathOriginal=${nomOriginal%/*} # chemin du repertoire original
				pathModif=${nomModif%/*} # chemin apres modif
				if [[ "$pathOriginal" != "$pathModif" ]]; then # si les chemins sont differents , c' est que l' arborescence a été modifiée :
					nomModif="$pathModif"/"${nomModif##*/}" # dans ce cas on utilise l' arborescence modifiée precedemment + le nom modifié du dernier argument pour la destination
				fi

				# eviter les doublons et renommer correctement quand meme :
				directory="${nomModif%/*}"
				cleanFileName="${nomModif##*/}"
				base="$cleanFileName"
				ext=""
				suffix=0

				if [[ "$cleanFileName" == .* ]]; then
					base="${cleanFileName:1}" # Fichier caché (ex: .bash_profile) , Enlève le point initial
					if [[ "$base" == *.* ]]; then
						ext=".${base##*.}"
						base="${base%.*}"
					fi
				else
					if [[ "$cleanFileName" == *.* ]]; then # Fichier normal (ex: fichier.txt)
						ext=".${cleanFileName##*.}"
						base="${cleanFileName%.*}"
					fi
				fi

				while [[ -e "$nomModif" ]]; do
					nomModif="${directory}/${base}_${suffix}${ext}"
					((suffix++))
				done

				echo "renommage du fichier : mv '$nomOriginal' ==> '$nomModif'"
				if test "$modif_activ" = true; then
					mv  "$nomOriginal" "$nomModif"
					NbFileModified+=1
					echo "$NbFileModified RENOM : mv '$nomOriginal' en : '$nomModif'" >> "$log_modifs"
				fi
			fi
		fi
	fi
done

echo;
echo "récapitulatif : modif count = $count"
echo "$NbRepScanned dossiers et $NbFileScanned fichiers traités, $NbRepModified répertoires modifiés, $NbFileModified fichiers modifiés , le tout en $(($(date +%s)-Debut)) secondes."
(( NbNOTScanned )) && echo "$NbNOTScanned non traités."
echo;
(( NbFileModified || NbRepModified )) && echo "Pour voir les modifications : cat '/tmp/modifs'"
(( NbRepModified )) && echo "pour supprimer les dossiers vides , copiez collez la commande suivante : find '${execDir:=$PWD}' -type d -empty -delete"
echo;
if (( NbFileNOTModified || NbRepNOTModified || LongPath)); then
	echo "$NbFileNOTModified fichiers , $NbRepNOTModified répertoires n ' ayant pas pu etre modifiés"
	echo "vous avez $LongPath répertoires de taille trop importante."
	echo "liste des erreurs : cat '$log_error'"
	echo;
fi

Dernière modification par iznobe (Le 28/04/2026, à 13:53)

Hors ligne

#124 Le 28/04/2026, à 15:35

iznobe

Re : [RESOLU] script mettre en conformité les noms de fichiers samba

Maintenant que la fonction marche .... pourquoi est ce que le awk ne fait pas cette partie du travail ?

clean_name() { # Nettoie un nom de fichier/dossier
    printf '%s' "$1" | awk '
  BEGIN {
    IGNORECASE = 1

    reserved["NUL"]; reserved["PRN"]; reserved["CON"]; reserved["AUX"]
    for (i=0;i<=9;i++) { reserved["COM" i]; reserved["LPT" i] }
    reserved["COM¹"]; reserved["COM²"]; reserved["COM³"]
    reserved["LPT¹"]; reserved["LPT²"]; reserved["LPT³"]
  }
    {
        # trim
        gsub(/^[[:space:]]+|[[:space:]]+$/, "")

        # espaces autour /
        gsub(/[[:space:]]*\/[[:space:]]*/, "/")

        # espaces multiples
        gsub(/[[:space:]]+/, " ")

        # caractères interdits + contrôle
        gsub(/['"'"'\\:\*\?\"<>\|\001-\037\177]/, "_")

        # suppression points finaux
        sub(/\.+$/, "")

        # nettoyage dernier point
        if (match($0, /[[:space:]]*\.[[:space:]]*([^.]+)$/)) {
            ext = substr($0, RSTART, RLENGTH)
            sub(/^[[:space:]]*\.[[:space:]]*/, ".", ext)
            $0 = substr($0, 1, RSTART-1) ext
        }

        # uniquement des points → vide
        if ($0 ~ /^\.*$/) $0=""

            # basename sans extension
            base = $0
            sub(/\..*$/, "", base)

			if (toupper(base) in reserved) {
				$0 = base "_" substr($0, length(base)+1)
			}

            # vide → NONAME
            if ($0 ~ /^[[:space:]]*$/) $0="NONAME"

                print
            }'
        }

Dernière modification par iznobe (Le 28/04/2026, à 16:32)

Hors ligne

#125 Le 28/04/2026, à 17:41

iznobe

Re : [RESOLU] script mettre en conformité les noms de fichiers samba

Du coup nettoyage du code et re optimisation :


il doit bien rester quelques broutilles , non ?

ben voui , j ' allais oublié la recirculation en cas de déplacement / renommage de dossier :

#!/bin/bash

# Description des variables :
# $nomOriginal = nom complet rep ou fichier original
# $pathOriginal = chemin du repertoire original
# $nomModif = nom complet rep ou fichier modifié
# $pathModif = chemin du repertoire modifié
# $cleanFileName = nom fichier nettoyé
# FPNWE = chemin du fichier complet sans .ext = Full Path Name Without Extension
# $ext = extension du fichier le cas échéant sinon , renvoie le chemin complet du fichier.

# --- Configuration ---

modif_activ=false  # true pour appliquer les modifications

#### FIN ####

# --- Variables globales ---
declare -i count=0 LongPath=0 NbNOTScanned=0 NbRepScanned=0 NbFileScanned=0 NbRepModified=0 NbFileModified=0 NbRepNOTModified=0 NbFileNOTModified=0; Debut=$(date +%s);
declare log_error="/tmp/error.log" log_modifs="/tmp/modifs"

# --- Initialisation ---
shopt -s globstar nullglob
test -z "$log_error" && echo "liste des erreurs ( fichiers ou dossiers ) n ' ayant pas pu etre modifiés :" > "$log_error"
test -z "$log_modifs" && echo "-------------------" > "$log_modifs"
execDir="$1"

clean_name() { # Nettoie un nom de fichier/dossier
	printf '%s' "$1" | awk '
	BEGIN {
		IGNORECASE = 1

		reserved["NUL"]; reserved["NULL"]; reserved["PRN"]; reserved["CON"]; reserved["AUX"]; reserved["CLOCK$"]
		for (i=0;i<=9;i++) { reserved["COM" i]; reserved["LPT" i] }
		reserved["COM¹"]; reserved["COM²"]; reserved["COM³"]
		reserved["LPT¹"]; reserved["LPT²"]; reserved["LPT³"]
	}
	{
		# trim
		gsub(/^[[:space:]]+|[[:space:]]+$/, "")

		# espaces autour /
		gsub(/[[:space:]]*\/[[:space:]]*/, "/")

		# espaces multiples
		gsub(/[[:space:]]+/, " ")

		# caractères interdits + contrôle
		gsub(/['\''"\\:\*\?\"<>\|\001-\037\177]/, "_")

		# suppression points finaux
		sub(/\.+$/, "")

		# nettoyage dernier point
		if (match($0, /[[:space:]]*\.[[:space:]]*([^.]+)$/)) {
			ext = substr($0, RSTART, RLENGTH)
			sub(/^[[:space:]]*\.[[:space:]]*/, ".", ext)
			$0 = substr($0, 1, RSTART-1) ext
		}

		# uniquement des points → vide
		if ($0 ~ /^\.*$/) $0=""

		# basename sans extension
		base = $0
		sub(/\..*$/, "", base)

		if (toupper(base) in reserved) {
			$0 = base "_" substr($0, length(base)+1)
		}

		# vide → NONAME
		if ($0 ~ /^[[:space:]]*$/) $0="NONAME"

			print  # <-- Ici, le print est bien dans le bloc !
		}'
}

for nomOriginal in "${execDir:=$PWD}"/**/*; do

	if test -L "$nomOriginal"; then
		((NbNOTScanned++))
		continue
	fi

	pathOriginal="${nomOriginal%/*}" # get original pathname
	file="${nomOriginal##*/}" # get file name or directory name

	if test -f "$nomOriginal"; then
		((NbFileScanned++))
	else
		((NbRepScanned++))
	fi

	nomModif="$pathOriginal/$(clean_name "$file")"

	###############################"

	if [[ "$nomOriginal" != "$nomModif" ]]; then # si il y a un changement a effectuer
		((count++))
		# le nom du chemin ne doit pas dépasser 256 en standard , et chemin étendu 32767 max , prefixe windows = "\\?\"
		if (( "${#nomModif}" >= 256 )) ; then # Vérifions si la longueur n'est pas excessive
			((LongPath++))
			echo "Le nom de chemin de fichier est trop long ! impossible de renommer '$nomOriginal' en '$nomModif'" >> "$log_error"
		fi

		if test -d "$nomOriginal"; then # si c' est un dossier
			if test ! -w "$(realpath "${nomOriginal}"/..)"; then # on verifie si le dossier parent est modifiable
				((NbRepNOTModified++))
				echo "permission refusée : impossible de renommer '$nomOriginal' en '$nomModif'"
				echo "$NbRepNOTModified permission refusée : impossible de renommer '$nomOriginal' en '$nomModif'" >> "$log_error"
			else # eviter les doublons et renommer correctement quand meme :

				suffix=0
				while test -e "$nomModif"; do # Tant que le dossier cible existe déjà
					nomModif="${nomModif}_${suffix}"
					((suffix++))
				done

				echo "dossier renommé : mkdir '$nomOriginal' ==> '$nomModif'"
				if test "$modif_activ" = true; then
					mv -v "$nomOriginal" "$nomModif"
					((NbRepModified++))
					echo "$NbRepModified CREER_REP : mkdir '$nomModif'" >> "$log_modifs"
					bash "$0" "$nomModif"
				fi
			fi
		elif test -f "$nomOriginal" ; then # si c est un fichier
			if test ! -w "$(dirname "${nomOriginal}")"; then # on verifie si le dossier parent est modifiable
				((NbFileNOTModified++))
				echo "permission refusée : impossible de renommer '$nomOriginal' en '$nomModif'"
				echo "$NbFileNOTModified : permission refusée : impossible de renommer '$nomOriginal' en '$nomModif'" >> "$log_error"
			else
				pathModif=${nomModif%/*} # chemin apres modif
				if [[ "$pathOriginal" != "$pathModif" ]]; then # si les chemins sont differents , c' est que l' arborescence a été modifiée :
					nomModif="$pathModif"/"${nomModif##*/}" # dans ce cas on utilise l' arborescence modifiée precedemment + le nom modifié du dernier argument pour la destination
				fi

				# eviter les doublons et renommer correctement quand meme :
				directory="${nomModif%/*}"
				cleanFileName="${nomModif##*/}"
				base="$cleanFileName"
				ext=""
				suffix=0

				if [[ "$cleanFileName" == .* ]]; then
					base="${cleanFileName:1}" # Fichier caché (ex: .bash_profile) , Enlève le point initial
					if [[ "$base" == *.* ]]; then
						ext=".${base##*.}"
						base="${base%.*}"
					fi
				else
					if [[ "$cleanFileName" == *.* ]]; then # Fichier normal (ex: fichier.txt)
						ext=".${cleanFileName##*.}"
						base="${cleanFileName%.*}"
					fi
				fi

				while [[ -e "$nomModif" ]]; do
					nomModif="${directory}/${base}_${suffix}${ext}"
					((suffix++))
				done

				echo "renommage du fichier : mv '$nomOriginal' ==> '$nomModif'"
				if test "$modif_activ" = true; then
					mv  "$nomOriginal" "$nomModif"
					NbFileModified+=1
					echo "$NbFileModified RENOM : mv '$nomOriginal' en : '$nomModif'" >> "$log_modifs"
				fi
			fi
		fi
	fi
done

echo;
echo "récapitulatif : modif count = $count"
echo "$NbRepScanned dossiers et $NbFileScanned fichiers traités, $NbRepModified répertoires modifiés, $NbFileModified fichiers modifiés , le tout en $(($(date +%s)-Debut)) secondes."
(( NbNOTScanned )) && echo "$NbNOTScanned non traités."
echo;
(( NbFileModified || NbRepModified )) && echo "Pour voir les modifications : cat '/tmp/modifs'"
(( NbRepModified )) && echo "pour supprimer les dossiers vides , copiez collez la commande suivante : find '${execDir:=$PWD}' -type d -empty -delete"
echo;
if (( NbFileNOTModified || NbRepNOTModified || LongPath)); then
	echo "$NbFileNOTModified fichiers , $NbRepNOTModified répertoires n ' ayant pas pu etre modifiés"
	echo "vous avez $LongPath répertoires de taille trop importante."
	echo "liste des erreurs : cat '$log_error'"
	echo;
fi

Existe il un moyen plus élégant / performant d ' établir la " recirculation " du dossier déplacé , plutôt que de faire :

if test -d "$nomOriginal"; then # si c' est un dossier
  ....
  ...
                                if test "$modif_activ" = true; then
					mv -v "$nomOriginal" "$nomModif"
					((NbRepModified++))
					echo "$NbRepModified CREER_REP : mkdir '$nomModif'" >> "$log_modifs"
					bash "$0" "$nomModif"
				fi

?

Dernière modification par iznobe (Le 29/04/2026, à 09:59)

Hors ligne