Je fais un script bash pour faire une recherche de fichier contenant
certains caractères.
Je souhaite que le dossiers dans lequel se fait la recherche soit un
paramètre passé Í la commande find, de même que pour le/les dossiers Í
exclure, et c'est bien sur ce dernier point que se pose le problème.
En effet, si je ne m'abuse, pour exclure les fichiers d'un chemin, il
faut utiliser la syntaxe :
-not -path "chemin/*"
Or, quand je construis ma commande de la sorte, l'exclusion n'est pas
prise en compte. Pourtant, cette même commande fonctionne dans un shell
bash.
Il me semble que le problème se situe au niveau de l'expansion du "*"
final mais je ne parviens pas Í trouver comment le résoudre.
Pour clarifier mes explications, une version simplifiée du script :
#!/bin/bash
DIRS="/chemin/"
EXCLUDES="/chemin/a_exclure"
EXfor DIR in $EXCLUDES; do
EX="$EX -not -path \"$DIR/*\""
done
LISTE=$(find $DIRS $EX -regex '.*[^a-zA-Z./_0-9-].*')
echo "$LISTE"
echo "find $DIRS $EX -regex '.*[^a-zA-Z./_0-9-].*'"
J'ai essayé pas mal de choses, en échappant \*, avec, sans ou en
échappant les ". sans résultat. Et mes multiples recherchent ne m'ont
sans doute pas amené aux bonnes réponses, qui existent forcément.
Cette action est irreversible, confirmez la suppression du commentaire ?
Signaler le commentaire
Veuillez sélectionner un problème
Nudité
Violence
Harcèlement
Fraude
Vente illégale
Discours haineux
Terrorisme
Autre
Christophe PEREZ
Comme si le fait de poster la question faisait systématiquement réfléchir différemment, évident, j'ai trouvé ma réponse : Le Wed, 26 May 2021 19:15:12 +0000, Christophe PEREZ a écrit :
EX> for DIR in $EXCLUDES; do EX="$EX -not -path "$DIR/*"" done LISTE=$(find $DIRS $EX -regex '.*[^a-zA-Z./_0-9-].*')
en remplaçant par un tableau, et en ne quotant plus la partie "-not -path" cela fonctionne. J'ai trop focalisé sur le * en fait. EX=() for DIR in $EXCLUDES; do EX+=(-not -path "$DIR/*" ) done find "$DIRS" "${EX[@]}" -regex '.*[^a-zA-Z./_0-9-].*'
Comme si le fait de poster la question faisait systématiquement réfléchir
différemment, évident, j'ai trouvé ma réponse :
Le Wed, 26 May 2021 19:15:12 +0000, Christophe PEREZ a écrit :
EX> for DIR in $EXCLUDES; do
EX="$EX -not -path "$DIR/*""
done LISTE=$(find $DIRS $EX -regex '.*[^a-zA-Z./_0-9-].*')
en remplaçant par un tableau, et en ne quotant plus la partie "-not -path"
cela fonctionne. J'ai trop focalisé sur le * en fait.
EX=()
for DIR in $EXCLUDES; do
EX+=(-not -path "$DIR/*" )
done
find "$DIRS" "${EX[@]}" -regex '.*[^a-zA-Z./_0-9-].*'
Comme si le fait de poster la question faisait systématiquement réfléchir différemment, évident, j'ai trouvé ma réponse : Le Wed, 26 May 2021 19:15:12 +0000, Christophe PEREZ a écrit :
EX> for DIR in $EXCLUDES; do EX="$EX -not -path "$DIR/*"" done LISTE=$(find $DIRS $EX -regex '.*[^a-zA-Z./_0-9-].*')
en remplaçant par un tableau, et en ne quotant plus la partie "-not -path" cela fonctionne. J'ai trop focalisé sur le * en fait. EX=() for DIR in $EXCLUDES; do EX+=(-not -path "$DIR/*" ) done find "$DIRS" "${EX[@]}" -regex '.*[^a-zA-Z./_0-9-].*'
Thomas
In article <s8m8rq$crj$, Christophe PEREZ wrote:
Comme si le fait de poster la question faisait systématiquement réfléchir différemment, évident, j'ai trouvé ma réponse :
ça m'est déjÍ arrivé de : - écrire un msg presque entier, - et le fait de m'arracher les cheveux pour trouver comment expliquer clairement mon pb aux autres, m'a permis de trouver la réponse avant de cliquer sur envoyer ! grrr ... il me semble que c'est un truc connu en pédagogie : le fait de vouloir transmettre ses connaissances aux autres, et de vouloir le faire bien, permet de les approfondir et de les parfaire :-) -- RAPID maintainer http://savannah.nongnu.org/projects/rapid/
In article <s8m8rq$crj$2@vmserveur.novazur.fr>,
Christophe PEREZ <chris@novazur.fr> wrote:
Comme si le fait de poster la question faisait systématiquement réfléchir
différemment, évident, j'ai trouvé ma réponse :
ça m'est déjÍ arrivé de :
- écrire un msg presque entier,
- et le fait de m'arracher les cheveux pour trouver comment expliquer
clairement mon pb aux autres, m'a permis de trouver la réponse avant de
cliquer sur envoyer ! grrr ...
il me semble que c'est un truc connu en pédagogie :
le fait de vouloir transmettre ses connaissances aux autres, et de
vouloir le faire bien, permet de les approfondir et de les parfaire :-)
Comme si le fait de poster la question faisait systématiquement réfléchir différemment, évident, j'ai trouvé ma réponse :
ça m'est déjÍ arrivé de : - écrire un msg presque entier, - et le fait de m'arracher les cheveux pour trouver comment expliquer clairement mon pb aux autres, m'a permis de trouver la réponse avant de cliquer sur envoyer ! grrr ... il me semble que c'est un truc connu en pédagogie : le fait de vouloir transmettre ses connaissances aux autres, et de vouloir le faire bien, permet de les approfondir et de les parfaire :-) -- RAPID maintainer http://savannah.nongnu.org/projects/rapid/
Christian Weisgerber
On 2021-05-26, Christophe PEREZ wrote:
#!/bin/bash DIRS="/chemin/" EXCLUDES="/chemin/a_exclure" EX> for DIR in $EXCLUDES; do EX="$EX -not -path "$DIR/*"" done LISTE=$(find $DIRS $EX -regex '.*[^a-zA-Z./_0-9-].*')
Montrons les arguments exacts passés Í find : for i in $DIRS $EX -regex '.*[^a-zA-Z./_0-9-].*'; do echo "[$i]"; done [/chemin/] [-not] [-path] ["/chemin/a_exclure/*"] # !!! [-regex] [.*[^a-zA-Z./_0-9-].*] Aha ! Les guillemets sont préservés, donc les noms de fichiers ne correspondent pas au motif. Autre chose : Dans ce cas, car les guillemets résultent du remplacement d'un paramètre, ils n'empêchent pas le développement des noms de fichiers. Exemple : $ touch '"foo"' $ FOO='"*"' $ echo $FOO "foo" Le problème, c'est que tu veux (1) faire la séparation des mots et (2) empêcher le développement des noms de fichiers. Malheureusement, « "$EX" » empêche tous les deux et « $EX » permet tous les deux. Quoi faire ? Une solution possible, qui est disponible dans tous les shells POSIX, y compris bash, c'est supprimer le développement des noms de fichiers avec « set -f ». #!/bin/sh DIRS="/chemin/" EXCLUDES="/chemin/a_exclure" EX for DIR in $EXCLUDES; do EX="$EX -not -path $DIR/*" # <--- done set -f # <--- find $DIRS $EX -regex '.*[^a-zA-Z./_0-9-].*' PS : « -not » et « -regex » ne sont pas standard. Au place de « -not », utilise « ! ». Ici, « -regex » n'emporte pas d'avantage. On peut faire la même chose avec « -path » : -path '*[!a-zA-Z./_0-9-]*' -- Christian "naddy" Weisgerber
On 2021-05-26, Christophe PEREZ <chris@novazur.fr> wrote:
#!/bin/bash
DIRS="/chemin/"
EXCLUDES="/chemin/a_exclure"
EX> for DIR in $EXCLUDES; do
EX="$EX -not -path "$DIR/*""
done
LISTE=$(find $DIRS $EX -regex '.*[^a-zA-Z./_0-9-].*')
Montrons les arguments exacts passés Í find :
for i in $DIRS $EX -regex '.*[^a-zA-Z./_0-9-].*'; do echo "[$i]"; done
Aha ! Les guillemets sont préservés, donc les noms de fichiers ne
correspondent pas au motif.
Autre chose : Dans ce cas, car les guillemets résultent du remplacement
d'un paramètre, ils n'empêchent pas le développement des noms de
fichiers. Exemple :
$ touch '"foo"'
$ FOO='"*"'
$ echo $FOO
"foo"
Le problème, c'est que tu veux (1) faire la séparation des mots et
(2) empêcher le développement des noms de fichiers. Malheureusement,
« "$EX" » empêche tous les deux et « $EX » permet tous les deux.
Quoi faire ?
Une solution possible, qui est disponible dans tous les shells POSIX,
y compris bash, c'est supprimer le développement des noms de fichiers
avec « set -f ».
#!/bin/sh
DIRS="/chemin/"
EXCLUDES="/chemin/a_exclure"
EX for DIR in $EXCLUDES; do
EX="$EX -not -path $DIR/*" # <---
done
set -f # <---
find $DIRS $EX -regex '.*[^a-zA-Z./_0-9-].*'
PS :
« -not » et « -regex » ne sont pas standard.
Au place de « -not », utilise « ! ».
Ici, « -regex » n'emporte pas d'avantage. On peut faire la même chose
avec « -path » :
-path '*[!a-zA-Z./_0-9-]*'
--
Christian "naddy" Weisgerber naddy@mips.inka.de
#!/bin/bash DIRS="/chemin/" EXCLUDES="/chemin/a_exclure" EX> for DIR in $EXCLUDES; do EX="$EX -not -path "$DIR/*"" done LISTE=$(find $DIRS $EX -regex '.*[^a-zA-Z./_0-9-].*')
Montrons les arguments exacts passés Í find : for i in $DIRS $EX -regex '.*[^a-zA-Z./_0-9-].*'; do echo "[$i]"; done [/chemin/] [-not] [-path] ["/chemin/a_exclure/*"] # !!! [-regex] [.*[^a-zA-Z./_0-9-].*] Aha ! Les guillemets sont préservés, donc les noms de fichiers ne correspondent pas au motif. Autre chose : Dans ce cas, car les guillemets résultent du remplacement d'un paramètre, ils n'empêchent pas le développement des noms de fichiers. Exemple : $ touch '"foo"' $ FOO='"*"' $ echo $FOO "foo" Le problème, c'est que tu veux (1) faire la séparation des mots et (2) empêcher le développement des noms de fichiers. Malheureusement, « "$EX" » empêche tous les deux et « $EX » permet tous les deux. Quoi faire ? Une solution possible, qui est disponible dans tous les shells POSIX, y compris bash, c'est supprimer le développement des noms de fichiers avec « set -f ». #!/bin/sh DIRS="/chemin/" EXCLUDES="/chemin/a_exclure" EX for DIR in $EXCLUDES; do EX="$EX -not -path $DIR/*" # <--- done set -f # <--- find $DIRS $EX -regex '.*[^a-zA-Z./_0-9-].*' PS : « -not » et « -regex » ne sont pas standard. Au place de « -not », utilise « ! ». Ici, « -regex » n'emporte pas d'avantage. On peut faire la même chose avec « -path » : -path '*[!a-zA-Z./_0-9-]*' -- Christian "naddy" Weisgerber
Thomas
In article <s8m6o0$crj$, Christophe PEREZ wrote:
En effet, si je ne m'abuse, pour exclure les fichiers d'un chemin, il faut utiliser la syntaxe : -not -path "chemin/*"
le fait que * ne marche pas, ça doit être Í cause du moment o͹ le shell exécute l'expansion : il faut qu'il trouve un '*' Í ce moment lÍ : peut être '*' ? (je ne connais pas le shell suffisamment) mais je ne comprend pas pourquoi "-not -path chemin1/*" "-not -path chemin2/*" fonctionnerais, et pas "-not -path chemin1/* -not -path chemin2/*" par contre, pourquoi n'utilises tu pas -prune ? qui a l'air d'être fait pour ça d'après le man, pour éviter de parcourir des branches de l'arborescence que tu veux uniquement ignorer (je ne peux pas te dire précisément comment on s'en sert, parce que je ne connais pas suffisamment la grammaire des arguments de find) -- RAPID maintainer http://savannah.nongnu.org/projects/rapid/
In article <s8m6o0$crj$1@vmserveur.novazur.fr>,
Christophe PEREZ <chris@novazur.fr> wrote:
En effet, si je ne m'abuse, pour exclure les fichiers d'un chemin, il
faut utiliser la syntaxe :
-not -path "chemin/*"
le fait que * ne marche pas, ça doit être Í cause du moment o͹ le shell
exécute l'expansion : il faut qu'il trouve un '*' Í ce moment lÍ :
peut être '\*' ?
(je ne connais pas le shell suffisamment)
mais je ne comprend pas pourquoi
"-not -path chemin1/*" "-not -path chemin2/*"
fonctionnerais, et pas
"-not -path chemin1/* -not -path chemin2/*"
par contre, pourquoi n'utilises tu pas -prune ?
qui a l'air d'être fait pour ça d'après le man, pour éviter de parcourir
des branches de l'arborescence que tu veux uniquement ignorer
(je ne peux pas te dire précisément comment on s'en sert, parce que je
ne connais pas suffisamment la grammaire des arguments de find)
En effet, si je ne m'abuse, pour exclure les fichiers d'un chemin, il faut utiliser la syntaxe : -not -path "chemin/*"
le fait que * ne marche pas, ça doit être Í cause du moment o͹ le shell exécute l'expansion : il faut qu'il trouve un '*' Í ce moment lÍ : peut être '*' ? (je ne connais pas le shell suffisamment) mais je ne comprend pas pourquoi "-not -path chemin1/*" "-not -path chemin2/*" fonctionnerais, et pas "-not -path chemin1/* -not -path chemin2/*" par contre, pourquoi n'utilises tu pas -prune ? qui a l'air d'être fait pour ça d'après le man, pour éviter de parcourir des branches de l'arborescence que tu veux uniquement ignorer (je ne peux pas te dire précisément comment on s'en sert, parce que je ne connais pas suffisamment la grammaire des arguments de find) -- RAPID maintainer http://savannah.nongnu.org/projects/rapid/
Christophe PEREZ
Le Wed, 26 May 2021 23:28:00 +0200, Thomas a écrit :
ça m'est déjÍ arrivé de : - écrire un msg presque entier, - et le fait de m'arracher les cheveux pour trouver comment expliquer clairement mon pb aux autres, m'a permis de trouver la réponse avant de cliquer sur envoyer ! grrr ...
Alors je dois poster Í peine plus tÍ´t que toi, parce que moi, c'est toujours après avoir posté :D
il me semble que c'est un truc connu en pédagogie : le fait de vouloir transmettre ses connaissances aux autres, et de vouloir le faire bien, permet de les approfondir et de les parfaire
C'est sÍ»r que ça peut avoir une influence. Ça ne peut pas être du au hasard Í chaque fois. Pourtant, je t'assure que je tente toujours de faire preuve de méthode et de logique, et de faire toutes les recherches auxquelles je pense, avant de poster, puisque je sais ce qui m'arrive si souvent.
Le Wed, 26 May 2021 23:28:00 +0200, Thomas a écrit :
ça m'est déjÍ arrivé de :
- écrire un msg presque entier,
- et le fait de m'arracher les cheveux pour trouver comment expliquer
clairement mon pb aux autres, m'a permis de trouver la réponse avant de
cliquer sur envoyer ! grrr ...
Alors je dois poster Í peine plus tÍ´t que toi, parce que moi, c'est
toujours après avoir posté :D
il me semble que c'est un truc connu en pédagogie :
le fait de vouloir transmettre ses connaissances aux autres, et de
vouloir le faire bien, permet de les approfondir et de les parfaire
C'est sÍ»r que ça peut avoir une influence. Ça ne peut pas être du au
hasard Í chaque fois. Pourtant, je t'assure que je tente toujours de
faire preuve de méthode et de logique, et de faire toutes les recherches
auxquelles je pense, avant de poster, puisque je sais ce qui m'arrive si
souvent.
Le Wed, 26 May 2021 23:28:00 +0200, Thomas a écrit :
ça m'est déjÍ arrivé de : - écrire un msg presque entier, - et le fait de m'arracher les cheveux pour trouver comment expliquer clairement mon pb aux autres, m'a permis de trouver la réponse avant de cliquer sur envoyer ! grrr ...
Alors je dois poster Í peine plus tÍ´t que toi, parce que moi, c'est toujours après avoir posté :D
il me semble que c'est un truc connu en pédagogie : le fait de vouloir transmettre ses connaissances aux autres, et de vouloir le faire bien, permet de les approfondir et de les parfaire
C'est sÍ»r que ça peut avoir une influence. Ça ne peut pas être du au hasard Í chaque fois. Pourtant, je t'assure que je tente toujours de faire preuve de méthode et de logique, et de faire toutes les recherches auxquelles je pense, avant de poster, puisque je sais ce qui m'arrive si souvent.
Christophe PEREZ
Le Wed, 26 May 2021 23:47:25 +0200, Thomas a écrit :
le fait que * ne marche pas, ça doit être Í cause du moment o͹ le shell exécute l'expansion : il faut qu'il trouve un '*' Í ce moment lÍ : peut être '*' ? (je ne connais pas le shell suffisamment)
J'ai essayé pas mal de choses, mais de façon bien trop pifométrique.
mais je ne comprend pas pourquoi "-not -path chemin1/*" "-not -path chemin2/*" fonctionnerais, et pas "-not -path chemin1/* -not -path chemin2/*"
Je ne saurai te dire.
par contre, pourquoi n'utilises tu pas -prune ?
Tout simplement parce que toutes les recherches que j'ai faites pour exclure un chemin par find m'ont orienté vers ça et que je n'ai pas plus de compétence que toi pour mieux utiliser prune, même si je me souviens avoir déjÍ essayé.
qui a l'air d'être fait pour ça d'après le man, pour éviter de parcourir des branches de l'arborescence que tu veux uniquement ignorer (je ne peux pas te dire précisément comment on s'en sert, parce que je ne connais pas suffisamment la grammaire des arguments de find)
Il faut quand même avouer que find, c'est quand même un peu tordu, et pas très intuitif, c'est le moins que l'on puisse dire.
Le Wed, 26 May 2021 23:47:25 +0200, Thomas a écrit :
le fait que * ne marche pas, ça doit être Í cause du moment o͹ le shell
exécute l'expansion : il faut qu'il trouve un '*' Í ce moment lÍ :
peut être '\*' ?
(je ne connais pas le shell suffisamment)
J'ai essayé pas mal de choses, mais de façon bien trop pifométrique.
mais je ne comprend pas pourquoi "-not -path chemin1/*" "-not -path
chemin2/*"
fonctionnerais, et pas "-not -path chemin1/* -not -path chemin2/*"
Je ne saurai te dire.
par contre, pourquoi n'utilises tu pas -prune ?
Tout simplement parce que toutes les recherches que j'ai faites pour
exclure un chemin par find m'ont orienté vers ça et que je n'ai pas plus
de compétence que toi pour mieux utiliser prune, même si je me souviens
avoir déjÍ essayé.
qui a l'air d'être fait pour ça d'après le man, pour éviter de parcourir
des branches de l'arborescence que tu veux uniquement ignorer
(je ne peux pas te dire précisément comment on s'en sert, parce que je
ne connais pas suffisamment la grammaire des arguments de find)
Il faut quand même avouer que find, c'est quand même un peu tordu, et pas
très intuitif, c'est le moins que l'on puisse dire.
Le Wed, 26 May 2021 23:47:25 +0200, Thomas a écrit :
le fait que * ne marche pas, ça doit être Í cause du moment o͹ le shell exécute l'expansion : il faut qu'il trouve un '*' Í ce moment lÍ : peut être '*' ? (je ne connais pas le shell suffisamment)
J'ai essayé pas mal de choses, mais de façon bien trop pifométrique.
mais je ne comprend pas pourquoi "-not -path chemin1/*" "-not -path chemin2/*" fonctionnerais, et pas "-not -path chemin1/* -not -path chemin2/*"
Je ne saurai te dire.
par contre, pourquoi n'utilises tu pas -prune ?
Tout simplement parce que toutes les recherches que j'ai faites pour exclure un chemin par find m'ont orienté vers ça et que je n'ai pas plus de compétence que toi pour mieux utiliser prune, même si je me souviens avoir déjÍ essayé.
qui a l'air d'être fait pour ça d'après le man, pour éviter de parcourir des branches de l'arborescence que tu veux uniquement ignorer (je ne peux pas te dire précisément comment on s'en sert, parce que je ne connais pas suffisamment la grammaire des arguments de find)
Il faut quand même avouer que find, c'est quand même un peu tordu, et pas très intuitif, c'est le moins que l'on puisse dire.
Christophe PEREZ
Le Wed, 26 May 2021 21:42:15 +0000, Christian Weisgerber a écrit :
Le problème, c'est que tu veux (1) faire la séparation des mots et (2) empêcher le développement des noms de fichiers. Malheureusement, « "$EX" » empêche tous les deux et « $EX » permet tous les deux.
Ah voilÍ ! Merci pour toutes ces explications, que je vais prendre le temps de bien relire, voire tester pour bien comprendre.
Ici, « -regex » n'emporte pas d'avantage. On peut faire la même chose avec « -path » : -path '*[!a-zA-Z./_0-9-]*'
Exact ! Merci aussi pour ce complément de correction.
Le Wed, 26 May 2021 21:42:15 +0000, Christian Weisgerber a écrit :
Le problème, c'est que tu veux (1) faire la séparation des mots et (2)
empêcher le développement des noms de fichiers. Malheureusement,
« "$EX" » empêche tous les deux et « $EX » permet tous les deux.
Ah voilÍ !
Merci pour toutes ces explications, que je vais prendre le temps de bien
relire, voire tester pour bien comprendre.
Ici, « -regex » n'emporte pas d'avantage. On peut faire la même chose
avec « -path » :
-path '*[!a-zA-Z./_0-9-]*'
Le Wed, 26 May 2021 21:42:15 +0000, Christian Weisgerber a écrit :
Le problème, c'est que tu veux (1) faire la séparation des mots et (2) empêcher le développement des noms de fichiers. Malheureusement, « "$EX" » empêche tous les deux et « $EX » permet tous les deux.
Ah voilÍ ! Merci pour toutes ces explications, que je vais prendre le temps de bien relire, voire tester pour bien comprendre.
Ici, « -regex » n'emporte pas d'avantage. On peut faire la même chose avec « -path » : -path '*[!a-zA-Z./_0-9-]*'
Exact ! Merci aussi pour ce complément de correction.