#1 Le 14/09/2016, à 11:32
- abach
[Résolu] Espaces dans des noms de dossiers et de fichiers
Bonjour à tous et à toutes,
J'ai un problème que je n'arrive pas à résoudre. En fait, je ne sais même plus par quel bout le prendre.
J'ai des fichiers qui arrivent automatiquement dans une arborescence, créée elle aussi automatiquement, via un transfert FTP.
Ces fichiers sont des images et des vidéos provenant d'appareils de mesure. Les vidéos étant des avi et mon appli devant les visualiser ne gérant que les flv, j'ai écrit un script, basé sur ffmpeg, les transformant automatiquement. Ca marche bien, sauf que mon script ne gère pas les noms avec des espaces...
Le script, le voici :
#!/bin/bash
clear
PIDFILE=/tmp/.appli.pid
source=/media/abach/mediacenter/cameras
destination=/media/abach/raspdisk/www/appli/galleries
sourcefile="./.src.log"
radsource="$source/"
raddestination="$destination/"
logfile=$HOME/appli.log
function x1
{
echo "$1 `date +"%d/%m/%Y %H:%M:%S"`" >> $2
}
function xxx
{
chaine=${3#$1};
result=${chaine%$2};
echo "$result" >> "$4"
}
function decimal
{
res=`bc <<< "scale = 1; ( $1 / 10)"`
resdecimal="${res: -2}"
echo $resdecimal
}
function xfert
{
rsync -arz --exclude *.mp4 --exclude *.avi --exclude *.log --delete-after $1 $2
}
export -f decimal
export -f x1
export -f xxx
export -f xfert
if [ -f $PIDFILE ]
then
PID=$(cat $PIDFILE)
ps -p $PID > /dev/null 2>&1
if [ $? -eq 0 ]
then
x1 $logfile
x1 "Job is already running " $logfile
exit 1
else
## Process not found assume not running
echo $$ > $PIDFILE
if [ $? -ne 0 ]
then
x1 $logfile
echo "Could not create PID file" >> $logfile
exit 1
fi
fi
else
echo $$ > $PIDFILE
if [ $? -ne 0 ]
then
x1 $logfile
echo "Could not create PID file" >> $logfile
exit 1
fi
declare -a srcarray
# declare -a destarray
rm $sourcefile
# rm $destfile
rm $logfile
echo $radsource
x1 "appli.sh : " $logfile
x1 "==================== " $logfile
xfert $radsource $raddestination
x1 "Début : " $logfile
x1 "source : " $logfile
echo "source"
find $source -name '*.avi' -exec bash -c 'xxx '$radsource' ".avi" "$0" '$sourcefile' ' {} \; ;
x1 "Tableaux : " $logfile
echo "tableau"
x1 " source : " $logfile
echo "-- source"
index=0
for w in $(cat "$sourcefile");
do
srcarray[index]="$w"
index=$(expr $index + 1)
done
echo "--"
x1 "Tableau : " $logfile
echo "done"
echo "${#srcarray[@]} - ${#destarray[@]}" >> $logfile
echo "${#srcarray[@]} - ${#destarray[@]}"
x1 "Conversion : " $logfile
compteboucle=0
compteaction=0
for iii in "${srcarray[@]}"
do
((compteboucle++))
entree="$iii"
insource=0
if [ -f "$radsource$entree.avi" ] && [ ! -f "$radsource$entree.flv" ];
then
((compteaction++))
echo -n "$compteboucle-$compteaction : $radsource$entree.flv n'existe pas - "
/usr/bin/ffmpeg -y -i "$radsource$entree.avi" -vcodec flv -f flv -r 29.97 -filter:v scale=w=640:h=480 -aspect 4:3 -b:v 300k -g 160 -cmp dct -subcmp dct -mbd 2 -flags +aic+mv0+mv4 -trellis 1 -ac 1 -ar 22050 -b:a 56k "$radsource$entree.flv" >/dev/null 2>&1
echo "ok"
fi
echo "ok"
fi
cpt=$(decimal $compteaction)
if [ "$cpt" = ".0" ]
then
xfert $radsource $raddestination
fi
# test=$(echo "scale=1; $1/3" | bc)
done
find $source -name "*.avi" -type f -delete ;
x1 "Conversion : " $logfile
x1 "Transfert : " $logfile
xfert $radsource $raddestination
x1 "Transfert : " $logfile
# rsync -avrz --delete-after -L $source/*.jpg $destination
rm $PIDFILE
echo "$PIDFILE removed"
fi
Ma question du jour est de savoir comment gérer les noms de fichiers et de répertoire contenant des espaces...
J'ai cherché et j'ai trouvé des trucs avec "\042" mais rien à faire, je n'y arrive pas.
J'ai aussi cherché à tout renommer, fichiers et dossiers, via des mv, des sed... là encore sans résultat.
Si quelqu'un à une idée, je lui en suis d'avance reconnaissant.
Dernière modification par abach (Le 24/09/2016, à 11:26)
Les chiens vous regardent tous avec vénération. Les chats vous toisent tous avec dédain. Il n’y a que les cochons qui vous considèrent comme leurs égaux. - Winston Churchill
Je suis parrain Linux
Hors ligne
#2 Le 14/09/2016, à 11:39
- pingouinux
Re : [Résolu] Espaces dans des noms de dossiers et de fichiers
Bonjour,
Peux-tu préciser dans quelle partie du script le problème apparaît ? D'une façon générale, il faut utiliser des " ".
$ fichier="mon fichier avec des espaces"
$ echo "$fichier"
mon fichier avec des espaces
Dernière modification par pingouinux (Le 14/09/2016, à 11:40)
Hors ligne
#3 Le 14/09/2016, à 11:53
- abach
Re : [Résolu] Espaces dans des noms de dossiers et de fichiers
Un exemple est plus parlant :
/dossier/dossier 1
/fichier 1 plus un truc.avi
/fichier 2 avec autre chose.mp3
/file 4 xxx y ssss.jpg
/dossier numero 2
Tu vois, c'est pas fixe et ça dépend des sources...
Les espaces sont à la fois dans l'arborescence de répertoires et dans les noms de fichiers. J'ai aussi, bien sûr, pour compliquer le tout, plusieurs niveaux dans l'arborescence. C'est pour ça que find me semblait une bonne source de départ.
Les chiens vous regardent tous avec vénération. Les chats vous toisent tous avec dédain. Il n’y a que les cochons qui vous considèrent comme leurs égaux. - Winston Churchill
Je suis parrain Linux
Hors ligne
#4 Le 14/09/2016, à 11:58
- grigouille
Re : [Résolu] Espaces dans des noms de dossiers et de fichiers
Change IFS.
Par exemple, met
IFS='|'
$ ls -1
a b.txt
test.sh
$ cat test.sh
#/bin/bash
IFS='|'
for f in $(ls)
do
echo $f
done
$ ./test.sh
a b.txt
test.sh
$
Debian (xfce) 12
HP LaserJet M1132 MFP
Hors ligne
#5 Le 14/09/2016, à 12:37
- Watael
Re : [Résolu] Espaces dans des noms de dossiers et de fichiers
modifier l'IFS, mais que c'est laid ! en plus, tu ne le restaureS même pas !
et les guillemets autour des variables !?
salut abach,
attention, ligne 116, il y a un fi qui semble ne dépendre d'aucun if.
pour lire un fichier, on utilise une boucle while :
while read line; do echo "$line"; done
pour gérer les espaces dans les noms de fichiers, je vois deux solutions :
- faire afficher, par find, la liste des noms des fichiers séparés par NULL avec -print0, et piper cette sortie à une boucle while
l'intervention d'un tableau est-elle nécessaire ?
par exemple :
find ~ -maxdepth 1 -type f -print0 | while read -d '' filename; do : whatever with " $filename"; done
- positionner les options du shell nullglob (au cas où il n'y aurait pas de fichier) et globstar (pour descendre dans les sous-répertoires :
for f in "$src"/**/*.avi; do : whatever with "$f"; done
Dernière modification par Watael (Le 14/09/2016, à 17:41)
Connected \o/
Welcome to sHell. · eval is evil.
Hors ligne
#6 Le 14/09/2016, à 14:01
- grigouille
Re : [Résolu] Espaces dans des noms de dossiers et de fichiers
modifier l'IFS, mais que c'est laid ! en plus, tu ne le restaure même pas !
et les guillemets autour des variables !?
- tu restaures.
- Une remarque pertinente de ta part aurait été de dire que la ligne 1 de mon script test.sh n'est pas correct.
- IFS n'est pas changé dans le shell père :
$ echo "$IFS\c" | od -c
0000000 \t \n \ c \n
0000006
$ ./test.sh
a b.txt
test.sh
$ echo "$IFS\c" | od -c
0000000 \t \n \ c \n
0000006
$
Pour la restauration de l'IFS dans le shell enfant, je le laisse en exercice.
- Pourquoi mettre les guillemets autour de la variable f de mon exemple ? f ne sera jamais vide. Si il y a un cas qui génère un problème, je suis preneur d'explication.
- Nous avons proposé à abach plusieurs méthodes. À lui de faire son choix.
Debian (xfce) 12
HP LaserJet M1132 MFP
Hors ligne
#7 Le 14/09/2016, à 17:55
- Watael
Re : [Résolu] Espaces dans des noms de dossiers et de fichiers
il existe des best practices*, et parcourir la sortie d'une substitution de commande avec une boucle for (même en modifiant l'IFS) n'en fait pas partie.
*tu ne les suis pas, c'est ton problème; mais ne les défend pas comme si c'était de bonnes solutions.
tu continueras tout seul. <-point
Connected \o/
Welcome to sHell. · eval is evil.
Hors ligne
#8 Le 22/09/2016, à 21:03
- abach
Re : [Résolu] Espaces dans des noms de dossiers et de fichiers
Je reviens sur ce sujet.
J'ai réussi à faire une fonction que j'appelle dans un find. La fonction, la voici :
function rpl
{
a=`echo $0 | tr "[:blank:]" "_"`
if [ "$0" != "$a" ];
then
# echo "$0 - $b"
mv "$0" "$a" >/dev/null 2>&1
fi
}
Elle fonctionne parfaitement mais je voudrai l'étendre pour supprimer les caractère accentués et les trucs genre "ç". Je suis persuadé qu'en ajoutant quelque chose dans le tr, ça devrait marcher, ou alors en faisant des tr supplémentaires.
J'ai cherché pas mal de temps, fait un tas d'essais mais là, je sèche...
Les chiens vous regardent tous avec vénération. Les chats vous toisent tous avec dédain. Il n’y a que les cochons qui vous considèrent comme leurs égaux. - Winston Churchill
Je suis parrain Linux
Hors ligne
#9 Le 24/09/2016, à 09:33
- Ferod
Re : [Résolu] Espaces dans des noms de dossiers et de fichiers
Salut
http://www.commentcamarche.net/forum/af … s-accentue
Tu peux rajouter un tr 'àçéèëêïîöôùüûÀÇÉÈËÊÏÎÖÔÙÜÛ' 'aceeeeiioouuuACEEEEIIOOUUU' dans ta ligne a=...
a=`echo $0 | tr "[:blank:]" "_" | tr 'àçéèëêïîöôùüûÀÇÉÈËÊÏÎÖÔÙÜÛ' 'aceeeeiioouuuACEEEEIIOOUUU'`
j'ai pas testé mais ça doit marcher.
"When I was in the military, they gave me a medal for killing
two men, and a descharge for loving one !" Leonard Matlovich
Hors ligne
#10 Le 24/09/2016, à 11:25
- abach
Re : [Résolu] Espaces dans des noms de dossiers et de fichiers
Merci Ferod,
Au final, j'ai réussi à modifier ma fonction. Elle est la suivante :
function rpl
{
newfile=`echo $0 | sed -e "y/\/ÀÂÄâäàÊËÈÉéèêëÎÏîïÔÖôöÛÜûüùŶŸŷÿ/\/AAAaaaEEEEeeeeIIiiOOooUUuuuYYyy/; s/[ \t]/_/g; s/[^\/0-9a-zA-Z_.-]//g"`
if [ "$0" != "$newfile" ]; then
echo "-$0-$newfile-"
sleep 1
mv "$0" "$newfile"
fi
}
Je supprime ainsi tous les caractères qui ne passent pas (sauf si j'en ai oublié) en une ligne et un "sed". Je vais noter le pb résolu.
Encore merci à tous pour votre aide.
Les chiens vous regardent tous avec vénération. Les chats vous toisent tous avec dédain. Il n’y a que les cochons qui vous considèrent comme leurs égaux. - Winston Churchill
Je suis parrain Linux
Hors ligne
#11 Le 24/09/2016, à 11:36
- pingouinux
Re : [Résolu] Espaces dans des noms de dossiers et de fichiers
Pour être averti si "$newfile" existe déjà, je te conseille de remplacer
mv "$0" "$newfile"
par
mv -i "$0" "$newfile"
Tu peux en effet avoir des fichiers de noms différents qui prennent le même nom après transformation (âbc et äbc, par exemple).
Hors ligne