Script avec nom de fichier long avec espaces et parenthèses
Bruno83200_6929 Messages postés 626 Date d'inscription Statut Membre Dernière intervention -
Bonjour,
J'ai un nom de fichier long avec espaces et parenthèses et je dois faire un script bash qui déplace le fichier puis le renomme.
Lorsque je souhaite modifier le nom du fichier avec sed dans ce script, ça ne fonctionne pas. Je récupère dans un tableau le dernier nom du fichier copié ou créé. Puis avec sed je rajoute les slashs dans des chaines pour les espaces et parenthèses.
Mais lorsque je souhaite faire un ls avec le nom du fichier et les slashs, ça ne fonctionne pas.
Le code du script bash :
# Tableau qui indique le dernier fichier le plus récent copié dans le dossier declare -a tab eval "files=($(ls --quoting-style=shell-always -rt $DOSSIER_TELECHARGEMENTS_TERMINE))" for f in "${files[@]}"; do printf '%s\n' "$f" RT=`printf '%s\n' "$f"` tab[${#tab[*]}]=${RT} done # Récupere le nom du fichier dans le tableau NOM_DERNIER_FICHIER=${tab[-1]} echo "NOM_DERNIER_FICHIER : $NOM_DERNIER_FICHIER" # Traitement du fichier RT=`printf '%s\n' "$NOM_DERNIER_FICHIER"` NOM_DERNIER_FICHIER2=$(echo $NOM_DERNIER_FICHIER | sed s/' '/'\\ '/g) NOM_DERNIER_FICHIER3=$(echo $NOM_DERNIER_FICHIER2 | sed s/'('/'\\('/g) NOM_DERNIER_FICHIER4=$(echo $NOM_DERNIER_FICHIER3 | sed s/')'/'\\)'/g) NOM_DERNIER_FICHIER5=$(echo $NOM_DERNIER_FICHIER4 | sed s/'nom\'/'\mon '/g) echo "NOM_DERNIER_FICHIER2 : $NOM_DERNIER_FICHIER2" echo "NOM_DERNIER_FICHIER3 : $NOM_DERNIER_FICHIER3" echo "NOM_DERNIER_FICHIER4 : $NOM_DERNIER_FICHIER4" echo "NOM_DERNIER_FICHIER5 : $NOM_DERNIER_FICHIER5" echo echo "Liste le fichier" echo "ls -alh $DOSSIER_TELECHARGEMENTS_TERMINE/$NOM_DERNIER_FICHIER4" ls -alh $DOSSIER_TELECHARGEMENTS_TERMINE/$NOM_DERNIER_FICHIER4
Résultat :
NOM_DERNIER_FICHIER : mon fichier a des (parentheses).mkv sed: -e expression n°1, caractère 14: commande « s » inachevée NOM_DERNIER_FICHIER2 : mon\ fichier\ a\ des\ (parentheses).mkv NOM_DERNIER_FICHIER3 : mon\ fichier\ a\ des\ \(parentheses).mkv NOM_DERNIER_FICHIER4 : mon\ fichier\ a\ des\ \(parentheses\).mkv NOM_DERNIER_FICHIER5 : ls -alh /home/laurent/Test/mon\ fichier\ a\ des\ \(parentheses\).mkv ls: impossible d'accéder à '/home/laurent/Test/mon\': Aucun fichier ou dossier de ce type ls: impossible d'accéder à 'fichier\': Aucun fichier ou dossier de ce type ls: impossible d'accéder à 'a\': Aucun fichier ou dossier de ce type ls: impossible d'accéder à 'des\': Aucun fichier ou dossier de ce type ls: impossible d'accéder à '\(parentheses\).mkv': Aucun fichier ou dossier de ce type
L'erreur avec sed vient de cette ligne :
NOM_DERNIER_FICHIER5=$(echo $NOM_DERNIER_FICHIER4 | sed s/'nom\'/'\mon '/g)
Pourquoi la commande :
ls -alh $DOSSIER_TELECHARGEMENTS_TERMINE/$NOM_DERNIER_FICHIER4
... ne fonctionne pas depuis le script bash et me retourne
ls -alh /home/laurent/Test/mon\ fichier\ a\ des\ \(parentheses\).mkv ls: impossible d'accéder à '/home/laurent/Test/mon\': Aucun fichier ou dossier de ce type ls: impossible d'accéder à 'fichier\': Aucun fichier ou dossier de ce type ls: impossible d'accéder à 'a\': Aucun fichier ou dossier de ce type ls: impossible d'accéder à 'des\': Aucun fichier ou dossier de ce type ls: impossible d'accéder à '\(parentheses\).mkv': Aucun fichier ou dossier de ce type
Alors que depuis le shell ça fonctionne
laurent@vincent-I7-9700K:~$ ls -alh /home/laurent/Test/mon\ fichier\ a\ des\ \(parentheses\).mkv -rw-rw-r-- 1 laurent laurent 0 sept. 4 17:51 '/home/laurent/Test/mon fichier a des (parentheses).mkv' laurent@vincent-I7-9700K:~$
Pourtant depuis le script bash au ls, il y a bien les slashs pour les espaces et parenthèses.
J'ai besoin d'avoir dans la variable "NOM_DERNIER_FICHIER4" le nom de fichier avec les slashs pour ensuite déplacer et renommer le fichier.
mon\ fichier\ a\ des\ espaces\ et\ des\ \(parentheses\).mkv'
Merci d'avance pour votre avis et conseils.
Linux / Firefox 130.0
- Script avec nom de fichier long avec espaces et parenthèses
- Fichier bin - Guide
- Fichier epub - Guide
- Fichier rar - Guide
- Comment réduire la taille d'un fichier - Guide
- Fichier .dat - Guide
2 réponses
Bonjour,
Le problème que tu rencontres est lié au fait que dans un script bash, il n'est pas nécessaire d'échapper les espaces et les parenthèses de la manière que tu utilises (avec des backslashes) lorsque tu passes les variables aux commandes comme ls.
La gestion des espaces et des caractères spéciaux est automatiquement effectuée si tu utilises des guillemets autour des variables.
Voici comment tu peux simplifier ton script en utilisant correctement les guillemets dans les commandes pour éviter ce problème d'échappement manuel des espaces et des parenthèses :
# Tableau qui indique le dernier fichier le plus récent copié dans le dossier declare -a tab # Récupération des fichiers du dossier eval "files=($(ls --quoting-style=shell-always -rt $DOSSIER_TELECHARGEMENTS_TERMINE))" for f in "${files[@]}"; do printf '%s\n' "$f" tab[${#tab[*]}]="$f" done # Récupération du nom du fichier dans le tableau NOM_DERNIER_FICHIER="${tab[-1]}" echo "NOM_DERNIER_FICHIER : $NOM_DERNIER_FICHIER" # Pas besoin de manipulation complexe avec sed # Juste s'assurer que la variable est correctement entourée de guillemets echo "Liste le fichier" echo "ls -alh \"$DOSSIER_TELECHARGEMENTS_TERMINE/$NOM_DERNIER_FICHIER\"" ls -alh "$DOSSIER_TELECHARGEMENTS_TERMINE/$NOM_DERNIER_FICHIER"
Et pour le retour :
# Tableau qui indique le dernier fichier le plus récent copié dans le dossier declare -a tab # Récupérer la liste des fichiers eval "files=($(ls --quoting-style=shell-always -rt $DOSSIER_TELECHARGEMENTS_TERMINE))" for f in "${files[@]}"; do printf '%s\n' "$f" tab[${#tab[*]}]="$f" done # Récupération du nom du fichier dans le tableau NOM_DERNIER_FICHIER="${tab[-1]}" echo "NOM_DERNIER_FICHIER : $NOM_DERNIER_FICHIER" # Lister le fichier echo "Liste le fichier" echo "ls -alh \"$DOSSIER_TELECHARGEMENTS_TERMINE/$NOM_DERNIER_FICHIER\"" ls -alh "$DOSSIER_TELECHARGEMENTS_TERMINE/$NOM_DERNIER_FICHIER"
Re,
Merci de votre réponse.
Script bash :
lastFic1=$(find "$DOSSIER_TELECHARGEMENTS_TERMINE" -maxdepth 1 -type f ! -name '.*' -printf '%T@ %p\0' | sort -nz -k1,1 | cut -z -d ' ' -f 2- | tail -z -n1 | xargs -0 echo) lastFic2=${lastFic1//[)(]} lastFic3=${lastFic2// /-} lastFic4=${lastFic1// /'\ '} lastFic5=${lastFic4// (/' \('} lastFic6=${lastFic5//)/'\)'} echo "lastFic1 : $lastFic1" echo "lastFic2 : $lastFic2" echo "lastFic3 : $lastFic3" echo "lastFic4 : $lastFic4" echo "lastFic5 : $lastFic5" echo "lastFic6 : $lastFic6" echo echo "mv -v $lastFic6 $lastFic3" mv -v "$lastFic6 $lastFic3"
retour :
mv "/home/laurent/Test/mon fichier a des espaces et des (parentheses).mkv\ /home/laurent/Test//home/laurent/Test/mon-fichier-a-des-espaces-et-des-parentheses.mkv mv: opérande de fichier cible manquant après '/home/laurent/Test/mon fichier a des espaces et des (parentheses).mkv /home/laurent/Test/mon-fichier-a-des-espaces-et-des-parentheses.mkv' Saisissez « mv --help » pour plus d'informations.
depuis le shell :
laurent@vincent-I7-9700K:~$ mv /home/laurent/Test/mon\ fichier\ a\ des\ espaces\ et\ des\ \(parentheses\).mkv /home/laurent/Test/mon-fichier-a-des-espaces-et-des-parentheses.mkv mv: impossible d'évaluer '/home/laurent/Test/mon fichier a des espaces et des (parentheses).mkv': Aucun fichier ou dossier de ce type laurent@vincent-I7-9700K:~$
Pourquoi la commande mv ne fonctionne pas ? Idem dans le shell, j'ai besoin de déplacer le fichier depuis le script bash.
D'où vient le problème ?
Merci.
Le problème vient du fait que la variable lastFic6 est mal construite et que les variables lastFic1 et lastFic6 ne sont pas correctement traitées.
#!/bin/bash # Trouver le fichier le plus récent lastFic1=$(find "$DOSSIER_TELECHARGEMENTS_TERMINE" -maxdepth 1 -type f ! -name '.*' -printf '%T@ %p\0' | sort -nz -k1,1 | cut -z -d ' ' -f 2- | tail -z -n1) # Remplacer les espaces par des tirets dans le nom du fichier lastFic2=${lastFic1// /-} # Remplacer les parenthèses par des chaînes échappées lastFic3=$(printf '%s' "$lastFic1" | sed 's/(/\\(/g; s/)/\\)/g') # Préparer le nouveau nom de fichier lastFic4=$(printf '%s' "$lastFic2" | sed 's/(/\\(/g; s/)/\\)/g') # Afficher les variables pour vérification echo "lastFic1 : $lastFic1" echo "lastFic2 : $lastFic2" echo "lastFic3 : $lastFic3" echo "lastFic4 : $lastFic4" # Vérifier les chemins des fichiers if [ -e "$lastFic1" ]; then echo "Le fichier source existe : $lastFic1" else echo "Le fichier source n'existe pas : $lastFic1" exit 1 fi # Déplacer et renommer le fichier echo "mv -v \"$lastFic1\" \"$lastFic4\"" mv -v "$lastFic1" "$lastFic4"
- lastFic1 : Contient le chemin du fichier le plus récent trouvé.
- lastFic2 : Remplace les espaces par des tirets dans le nom du fichier.
- lastFic3 : Échappe les parenthèses pour une utilisation dans les commandes, mais ce n'est pas nécessaire pour la commande mv avec des guillemets correctement utilisés.
- lastFic4 : Contient le nouveau nom du fichier après avoir remplacé les espaces par des tirets.
Validation : Vérifie si le fichier source existe avant d'exécuter la commande mv.
Utilisation correcte de mv : Les variables sont entourées de guillemets pour gérer correctement les espaces et les caractères spéciaux dans les chemins de fichiers.
Avec ce script simplifié, tu devrais être capable de déplacer et renommer les fichiers correctement. Assure-toi que le chemin du fichier source existe réellement et que les chemins des fichiers sont correctement construits.