Contenu | Rechercher | Menus

Annonce

Si vous avez des soucis pour rester connecté, déconnectez-vous puis reconnectez-vous depuis ce lien en cochant la case
Me connecter automatiquement lors de mes prochaines visites.

À propos de l'équipe du forum.

#1 Le 11/06/2014, à 10:53

Vicolaships

[Résolu]find + -exec + rm

Salut,

Je suis coincé avec une ligne de commande je trouve pas mon erreur.
Je cherche à parcourir tout les sous dossier répertoires "build" d'un répertoire et supprimer tout leur contenu.

Trouver tout les dossier build

$ find . -type d -name "build"

Lister le contenu de tout les dossiers build.

$ find . -type d -name "build" -exec ls {} \;

Et maintenant j'essaie de supprimer le contenu des dossier build au lieu de lister le contenu:

$ find . -type d -name "build" -exec rm {}/* \;
rm: cannot remove `./build/*': No such file or directory

Pourtant la commande rm ./build/* supprime bien les fichiers.
Où est mon erreur ?

A+

Dernière modification par Vicolaships (Le 11/06/2014, à 14:56)


Ubuntu 14.04 x64

Hors ligne

#2 Le 11/06/2014, à 11:43

Nolanux

Re : [Résolu]find + -exec + rm

et si tu essaies ceci ?

$ find . -type d -name "build" -exec rm -r {}/* \;

Pas démonter Numéro 5 !
"Short Circuit"

Hors ligne

#3 Le 11/06/2014, à 11:53

tiramiseb

Re : [Résolu]find + -exec + rm

Salut,

Il est fort possible que l'astérisque ne soit pas interprété lors de l'exécution de la commande rm par find.
C'est une incompréhension assez courante : en fait, ce n'est pas donner « * » à rm qui fait qu'il efface tous les fichiers ; quand on tape « rm * », c'est le shell qui interprète l'astérisque et qui donne à rm la liste de tous les fichiers concernés...

Hors ligne

#4 Le 11/06/2014, à 11:54

casperfr

Re : [Résolu]find + -exec + rm

Bonjour

Nolanux a écrit :

et si tu essaies ceci ?

$ find . -type d -name "build" -exec rm -r {}/* \;

le -r voulant dire récursif, dans ce cas qu'elle est l'utilisé de concervé le /*
je rajouterais aussi -f pour évité de demander la confirmation

$ find . -type d -name "build" -exec rm -rf {} \;

Hors ligne

#5 Le 11/06/2014, à 11:57

tiramiseb

Re : [Résolu]find + -exec + rm

Attention, la proposition de casperfs supprime les répertoires "build" eux-mêmes et pas seulement leur contenu.

Cela étant dit, cette proposition peut être rendu encore plus performante en remplaçant ";" par "+" :

$ find . -type d -name "build" -exec rm -rf {} +

(mais ça efface toujours encore les répertoires "build" eux-mêmes...)

Hors ligne

#6 Le 11/06/2014, à 11:59

casperfr

Re : [Résolu]find + -exec + rm

effectivement tu as raison tiramiseb merci pour ce complément, je n'y avait même pas pensé

@tiramiseb
peut on chainé des commandes par ce principe pour évité ce désagrément ?
par exemple :

$ find . -type d -name "build" -exec rm -rf {};mkdir -p {} +

ou

$ find . -type d -name "build" -exec rm -rf {} -exec mkdir -p {} +

Dernière modification par casperfr (Le 11/06/2014, à 12:06)

Hors ligne

#7 Le 11/06/2014, à 12:46

Vicolaships

Re : [Résolu]find + -exec + rm

Merci pour les réponses et explications.
Je ne savais pas que c'était le shell qui allait chercher la liste des fichiers quand on utilise "*", d'un côté ça parait assez logique.

Pour la signification de ";" et "+" :
http://unixhelp.ed.ac.uk/CGI/man-cgi?find

Si possible j'aimerai ne pas supprimer le dossier build (ca m'évitera de le recréer juste après roll Mais finalement c'est pas aussi simple que je le pensais.
L'option -delete de find ne permet pas de supprimer les dossiers non vides.

@casperfr
On ne peut utiliser qu'une seule instance de {} dans une commande exec; donc je crois pas que ça soit possible

J'ai essayé avec l'option -execdir mais on retombe sur le même problème de l'astérisque

$ find . -type d -name "build" -execdir rm -r ./build/* \;

Quelqu'un a mieux ? tongue


Ubuntu 14.04 x64

Hors ligne

#8 Le 11/06/2014, à 14:05

casperfr

Re : [Résolu]find + -exec + rm

quelque chose comme ça ne pourrais pas marché en reprenant l'idée de tout a l'heure

for fic in $(find . -type d -name "build" ); do rm -rf $fic ; mkdir -p $fic ; done

Dernière modification par casperfr (Le 11/06/2014, à 14:21)

Hors ligne

#9 Le 11/06/2014, à 14:55

Vicolaships

Re : [Résolu]find + -exec + rm

Ça fait ce que je voulais !
Bien joué big_smile

Par contre ça fait des bêtises avec les noms de répertoires contenant des espaces. C'est pas très grave mais je suis preneur si quelqu'un a mieux !

Dernière modification par Vicolaships (Le 11/06/2014, à 15:01)


Ubuntu 14.04 x64

Hors ligne

#10 Le 11/06/2014, à 17:47

tiramiseb

Re : [Résolu]find + -exec + rm

Par contre ça fait des bêtises avec les noms de répertoires contenant des espaces. C'est pas très grave mais je suis preneur si quelqu'un a mieux !

Entoure les variables avec des guillemets, utilise while/read plutôt que for et tant qu'à faire, plutôt que détruire et reconstruire le répertoire build, supprime son contenu :

find . -type d -name "build" | while read fic
do
  rm -rf "$fic"/*
done

Hors ligne

#11 Le 11/06/2014, à 18:24

casperfr

Re : [Résolu]find + -exec + rm

si je proposais la reconstruction c'est parce que dans ma tête je me disais que comme il n'y avait pas de listage des fichiers via le /* la supprimer elle pourrait etre plus rapide,
mais je me trompe peux etre.
c'est vrai que je ne penses jamais a utilisé le while

EDIT:
pour le problème des espaces :

IFS=$'\n' ; for fic in $(find . -type d -name "build" ); do rm -rf "$fic" ; mkdir -p "$fic" ; done

Dernière modification par casperfr (Le 11/06/2014, à 20:53)

Hors ligne

#12 Le 11/06/2014, à 20:29

tiramiseb

Re : [Résolu]find + -exec + rm

je me disais que comme il n'y avait pas de listage des fichiers via le /* la supprimer elle pourrait etre plus rapide

Il n'y a pas ce listage dans le "-exec" de find, mais là tu es en dehors, donc ça fonctionne smile

Hors ligne

#13 Le 11/06/2014, à 21:15

casperfr

Re : [Résolu]find + -exec + rm

Merci pour toutes tes explications tiramiseb,

ce que je voulais dire par listage c'est que lors de la commande

rm -fr /dossier/*

comme il y a le listage des fichiers a supprimer,
je me demandais si la commande

rm -rf /dossier
mkdir -p /dossier

aurais pus être plus rapide
c'est pour cela que j'ai proposé a Vicolaships la solution en 2 étapes avec suppression puis reconstruction
je suis d'accord sur le faite que de faire une seule ligne de commande est plus propre que d'en faire plusieurs
il faudrait que j'essai pour voir, mais je me trompe peut être totalement

EDIT :
j'ai créé 10000 fichier dans un dossier

mkdir dossier
cd dossier
touch {1..10000}.txt
cd ..

et voila ce que j'ai obtenu

$ time rm -rf dossier/*
real    0m0.281s
user    0m0.196s
sys     0m0.088s
$ time rm -rf dossier ; mkdir -p dossier
real    0m0.143s
user    0m0.016s
sys     0m0.120s

donc la suppression directe du dossier plus la recréation de celui ci est 2 fois plus rapide que la suppression du contenu du dossier
enfin dans mon test avec des fichiers vide

Dernière modification par casperfr (Le 11/06/2014, à 21:35)

Hors ligne

#14 Le 12/06/2014, à 08:56

Postmortem

Re : [Résolu]find + -exec + rm

Salut,
Directement avec find sans recréation du répertoire :

find . -path '*/build/*' ! -name 'build' -delete
casperfr a écrit :

pour le problème des espaces :

IFS=$'\n' ; for fic in $(find . -type d -name "build" ); do rm -rf "$fic" ; mkdir -p "$fic" ; done

Ça, c'est très laid, la solution de tiramiseb est mieux. Et encore mieux à mon sens :

while read -rd ''
do
   echo "$REPLY"
done < <(find . -print0)

L'avantage, c'est que ça prend en compte les noms de fichier comprenant des retours à la ligne (c'est pas commun mais ça peut servir) et surtout, les variables modifiées dans la boucle sont accessible après celle-ci :

$ c=0
$ find . | while read fic
> do
> ((c++))
> done
$ echo $c
0

$ c=0
$ while read -rd ''
> do
> ((c++))
> done < <(find . -print0)
$ echo $c
23

Mot' a dit : « Un Hellfest sans Slayer, c'est comme une galette-saucisse sans saucisse ! »

Hors ligne

#15 Le 12/06/2014, à 10:00

Vicolaships

Re : [Résolu]find + -exec + rm

donc la suppression directe du dossier plus la recréation de celui ci est 2 fois plus rapide que la suppression du contenu du dossier
enfin dans mon test avec des fichiers vide

Intéressant ça ! De toute façon dans mon cas c'est jamais une arborescence avec 10 000 sous dossiers (ca ferait 10 000 projets roll)
La performance ça ne me préoccupe pas vraiment; même si c'est intéressant de s'y pencher.

J'aime bien ta proposition Postmortem c'est propre, ça fait moins bricolo que celle de capser ( wink ) !

Dernière modification par Vicolaships (Le 12/06/2014, à 10:00)


Ubuntu 14.04 x64

Hors ligne