Supprimez les caractères spéciaux et remplacez l'espace par _ des fichiers et des répertoires de manière récursive dans Bash

1

J'ai un script qui me donne quelques problèmes, je sais que je dois le refaire de manière récursive mais j'ai des problèmes. Le script doit renommer tous les fichiers et dossiers d’un dossier en supprimant les caractères spéciaux tels que $ -,) (! Et en remplaçant "" par "_".

Voici le morceau que je dois refaire:

# Rename directories
find "$ORIG_DIR" -name "*" -type d| while read dname
do
    NEW_DIR=`echo "$dname" |sed -E 's/^[ \t]*//g; s/[ \t]*$//g; s/\./_/g; s/\,/_/g; s/ /_/g'`

        # Rename files
        find "$ORIG_DIR" -name "*" -type f | while read fname
        do
            NEW_FNAME=`echo "$fname" |sed -E 's/^[ \t]*//g; s/[ \t]*$//g; s/\./_/g; s/(.*)_/\1\./; s/\,/_/g; s/ /_/g'`
            if [ -e $NEW_FNAME ]
            then
                echo "$NEW_FNAME already exists. Not replacing $fname"
            else
                echo "Replacing $fname with $NEW_FNAME"
                mv "$fname" $NEW_FNAME
            fi
        done

    if [ -e $NEW_DIR ]
    then
        echo "$NEW_DIR already exists. Not replacing $dname"
    else
        echo "Replacing $dname with $NEW_DIR"
        mv "$dname" $NEW_DIR
    fi
done

END
Erick
la source
Où avez-vous des problèmes avec ce script? Recevez-vous des messages d'erreur, fait-il autre chose que prévu?
nohillside
Le message d'erreur que je reçois à la fin est qu'il n'y a aucun fichier ou répertoire de ce type. Ce script ne supprimera pas non plus!, $ -) (
Erick
Eh bien, un problème avec le script est que les deux find les commandes traverseront toujours l’ensemble de l’arborescence (remplacez la fonctionnalité à l’intérieur par des instructions echo pour voir ce qui se passe).
nohillside

Réponses:

1

Non testé

find . -depth -print0 |
while IFS= read -d '' -r file; do
    dir=$(dirname "$file")
    base=$(basename "$file") 
    base=${base//[[:space:]]/_}         # change whitespace to underscores
    base=${base//[^[:alnum:]_.]/}       # delete any chars not alphanumeric _ .
    newname="$dir/$base"
    if [[ -e $newname ]]; then
        echo "'$newname' exists, not renaming '$file'"
    else
        echo mv "$file" "$newname"
    fi
done

Si ça vous va, supprimez le "echo"

La clé ici est l'option "-depth" à trouver. Il émettra "./sub dir / nom du fichier" avant "./sub dir". Sinon, si "./sub dir" est renommé "./subdir", vous obtiendrez une erreur "fichier non trouvé" lorsque la boucle while atteint "./sub dir / nom_fichier". En outre, cela signifie que vous n'avez pas besoin d'une logique différente pour les répertoires.

L'option "-print0" à rechercher et l'occupation autour de la commande de lecture permettent de s'assurer que les noms de fichiers comportant des espaces sont gérés correctement.

glenn jackman
la source
C'est un bon pas en avant mais c'est aller trop loin. Cela supprimera le "." avant l'extension de fichier qui n'est pas bon. En outre, je souhaite conserver les traits de soulignement et faire remplacer les espaces par des traits de soulignement. Deuxièmement, j'ai nommé le dossier dans la commande, à savoir le dossier A, mais le script a touché tous les dossiers du répertoire contenant le dossier A.
Erick