Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

scruter un repertoire pour deplacer des fichiers

9 réponses
Avatar
octane
Bonjour,

j'ai des utilisateurs qui peuvent poser des fichiers dans un
repertoire.
Je souhaite ecrire un script qui scrute un repertoire et qui deplace
les fichiers ailleurs dans l'arborescence.
Je lancerai ce script via cron toutes les 15 minutes.

Je pensais faire un
#! /bin/bash

for file in `find /var/www/depot/ -type f`
do
mv $file /var/www/a_traiter/
done


Mais ca ne passe pas. Mes utilisateurs nomment leurs fichiers
n'importe comment (espace, ponctuation, caracteres speciaux) et il
arrive que le mv se plante.

Comment faire?

Merci

9 réponses

Avatar
Luc.Habert.00__arjf
:

for file in `find /var/www/depot/ -type f`
do
mv $file /var/www/a_traiter/
done


Mais ca ne passe pas. Mes utilisateurs nomment leurs fichiers
n'importe comment (espace, ponctuation, caracteres speciaux) et il
arrive que le mv se plante.


Il suffit d'utiliser le -exec de find :

find /var/www/depot -type f -exec mv '{}' /var/www/a_traiter ';'

.

Avatar
octane
On 16 avr, 16:31, (Luc Habert)
wrote:
for file in `find /var/www/depot/ -type f`
do
mv $file /var/www/a_traiter/
done

Mais ca ne passe pas. Mes utilisateurs nomment leurs fichiers
n'importe comment (espace, ponctuation, caracteres speciaux) et il
arrive que le mv se plante.


Il suffit d'utiliser le -exec de find :

find /var/www/depot -type f -exec mv '{}' /var/www/a_traiter ';'

oui, mais j'ai un peu plus de choses dans la boucle do .. done

Entre autre je fais un
echo "un fichier $file a ete transfere"
et cron me maile le "echo", et je pense a terme faire des cas
selon le fichier (exemple: .doc -> /dev/null, .pdf -> a_traiter/
etc etc..)


Avatar
Luc.Habert.00__arjf
:

oui, mais j'ai un peu plus de choses dans la boucle do .. done


Alors au lieu du mv, tu fais lancer à find un shell exécutant ton corps de
boucle :

find /var/www/depot -type f -exec sh -c 'for file in "$@"; do corps de la boucle; done' ploum '{}' '+'

(tiens, j'avais mis un « ; », mais mieux vaut un « + », ça en passe
plusieurs d'un coup (mais il faut un find pas trop vieux pour ça)).

Avatar
octane
On 16 avr, 17:05, (Luc Habert)
wrote:
:

oui, mais j'ai un peu plus de choses dans la boucle do .. done


Alors au lieu du mv, tu fais lancer à find un shell exécutant ton cor ps de
boucle :

find /var/www/depot -type f -exec sh -c 'for file in "$@";
do corps de la boucle; done' ploum '{}' '+'

(tiens, j'avais mis un « ; », mais mieux vaut un « + », ça en p asse
plusieurs d'un coup (mais il faut un find pas trop vieux pour ça)).


Et je retombe sur mon probleme initial :)
que dois-je mettre dans <corps de la boucle> pour que le mv me
deplace les fichiers sans buter sur un fichier avec des caracteres
speciaux?
Plus, comment va se comporter le shell et le $@ avec des noms
de fichiers avec des caracteres speciaux?


Avatar
Luc.Habert.00__arjf
:

que dois-je mettre dans <corps de la boucle> pour que le mv me
deplace les fichiers sans buter sur un fichier avec des caracteres
speciaux?


Simplement mettre « "$file" » au lieu de « $file ».

En fait, ce qui se passait avec ce que tu faisais, c'est que dans ton

for file in `find /var/www/depot/ -type f`

le shell lit la sortie de find, la découpe sur le whitespace (plus
précisément les caractères contenus dans la variable IFS qui, par défaut,
contient le whitespace), et ensuite fait du globbing (interprétation des *
et cie) sur chaque morceau. Avec ce que je t'indique, ce découpage est
éliminé : l'écriture « "$@" » est spéciale, elle spécifie que ça donne la
liste des arguments passés au script, sans découpage ni globbing. Il reste
juste à ce que le « $file » ne se fasse pas découper dans le corps de la
boucle, et pour ça, il faut et il suffit de le mettre entre « " » à chaque
fois où tu t'en sers.

On ne le répètera jamais assez : il faut toujours mettre entre « " » les
expansions de variables, sauf si on veut vraiment du découpage et du
globbing, ce qui n'arrive pas si souvent que ça. (Et si on ne veut que l'un
des deux? Pour désactiver le découpage, il faut vider IFS, et pour
désactiver le globbing, il faut faire un « set -f ».)

Avatar
Mihamina (R12y) Rakotomandimby
Luc Habert - <f003cm$cj0$ :

j'avais mis un « ; », mais mieux vaut un « +


J'ai regardé dans le man find ce que ça signifiait. Pas trouvé. Dans le man
du shell (bash)? Trop "long"... Un coup de main?

Avatar
Stephane Chazelas
2007-04-18, 09:06(+02), Mihamina (R12y) Rakotomandimby:
Luc Habert - <f003cm$cj0$ :

j'avais mis un « ; », mais mieux vaut un « +


J'ai regardé dans le man find ce que ça signifiait. Pas trouvé. Dans le man
du shell (bash)? Trop "long"... Un coup de main?


http://www.opengroup.org/onlinepubs/009695399/utilities/find.html

Ne marche que quand + est l'argument suivant le {} et s'il n'y a
qu'un seul {}. Et ca remplace {} par autant de fichiers que
possibles. C'est la version standard du -print0 | xargs -r0 de
GNU en mieux car il n'affecte pas le stdin des commandes (cela
dit, il pourra etre moins efficace car s'il y a plusieurs
commandes lancees, find ne continuera pas sa descente pendant
que les commandes sont executees).

Bien que -exec ... {} + ait ete dans le standard depuis 15 ans
et que ca existe depuis 20, je crois que GNU find ne l'a inclu
que tres recemment, ca explique peut-etre pourquoi ca n'est pas
dans ta page de man.

--
Stéphane


Avatar
Nicolas George
Stephane Chazelas wrote in message
:
Bien que -exec ... {} + ait ete dans le standard depuis 15 ans
et que ca existe depuis 20, je crois que GNU find ne l'a inclu
que tres recemment, ca explique peut-etre pourquoi ca n'est pas
dans ta page de man.


Plus précisément, le ChangeLog indique que ça a commencé à fonctionner le
2005-01-15, et que c'est sorti dans la version 4.2.12.

Avatar
Cyrille Lefevre
Bonjour,

j'ai des utilisateurs qui peuvent poser des fichiers dans un
repertoire.
Je souhaite ecrire un script qui scrute un repertoire et qui deplace
les fichiers ailleurs dans l'arborescence.
Je lancerai ce script via cron toutes les 15 minutes.

Je pensais faire un
#! /bin/bash

for file in `find /var/www/depot/ -type f`
do
mv $file /var/www/a_traiter/
done


Mais ca ne passe pas. Mes utilisateurs nomment leurs fichiers
n'importe comment (espace, ponctuation, caracteres speciaux) et il
arrive que le mv se plante.


si find supporte -print0 et xargs -0 (zero), le plus simple est :

find /var/depot/www -type f -print0 |
xargs -0 -i mv {} /var/www/a_traiter

sinon, ca complique un peu, mais sans plus :

find /var/depot/www |
while read line; do
mv "${line}" /var/www/a_traiter
done

le pb etant le nombre d'execution de la commande mv,
1 par fichier, optimisons donc un peu (a la xargs) :

find /var/depot/www -type f |
# remplacement de tous les " par "
sed -e 's/"/&/g' |
(
# longueur maximale de la ligne de commande
limit000
# valeur initiale
args=mv
while read line; do
# si la limite est atteinte
if (( ${#args} + ${#line} + 1 > ${limit} )); then
# execution de la ligne de commande prepare
eval ${args} /var/www/a_traiter
# puis reinitialisation
args=mv
# pas de continue pour ne pas perdre l'argument courant
fi
# ajout de l'argument courant a la ligne de commande a executer
args="${args} "${line}""
done
# traitement de ce qui reste
eval ${args} /var/www/a_traiter
)

non verifie, mais je ne dois pas etre loin de la verite :)
de toutes les facons, s'il y a un bug, c'est un bon exercice...

Regards, Cordialement,

Cyrille Lefevre.
--
mailto:Cyrille.Lefevre-news%
supprimer "%nospam% et ".invalid" pour me repondre.
remove "%nospam" and ".invalid" to answer me.