Pages : 1
#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...
Sébastien Maccagnoni - https://www.maccagnoni.eu - https://www.domotego.com
Hors ligne
#4 Le 11/06/2014, à 11:54
- casperfr
Re : [Résolu]find + -exec + rm
Bonjour
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...)
Sébastien Maccagnoni - https://www.maccagnoni.eu - https://www.domotego.com
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 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 ?
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é
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
Sébastien Maccagnoni - https://www.maccagnoni.eu - https://www.domotego.com
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
Sébastien Maccagnoni - https://www.maccagnoni.eu - https://www.domotego.com
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
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 )
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 ( ) !
Dernière modification par Vicolaships (Le 12/06/2014, à 10:00)
Ubuntu 14.04 x64
Hors ligne