Script avec nom de fichier long avec espaces et parenthes

xunil2003 Messages postés 765 Date d'inscription mercredi 17 novembre 2004 Statut Membre Dernière intervention 5 septembre 2024 - Modifié le 6 sept. 2024 à 16:39
Bruno83200_6929 Messages postés 153 Date d'inscription jeudi 18 juin 2020 Statut Non membre Dernière intervention 11 septembre 2024 - 5 sept. 2024 à 20:26

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

A voir également:

2 réponses

Bruno83200_6929 Messages postés 153 Date d'inscription jeudi 18 juin 2020 Statut Non membre Dernière intervention 11 septembre 2024 25
Modifié le 6 sept. 2024 à 16:40

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"

0
xunil2003 Messages postés 765 Date d'inscription mercredi 17 novembre 2004 Statut Membre Dernière intervention 5 septembre 2024 14
Modifié le 6 sept. 2024 à 16:41

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.

0
Bruno83200_6929 Messages postés 153 Date d'inscription jeudi 18 juin 2020 Statut Non membre Dernière intervention 11 septembre 2024 25
Modifié le 6 sept. 2024 à 16:42

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.

0