Lorsque vous effectuez une search comme find -type d
, l'ajout de l'argument -print0 juste après la command find telle que find -print0 -type d
provoque la search de résultats plus que sans résultat.
Si vous comprenez les &&
et ||
opérateurs dans le shell (et aussi en C, C ++, et les langues dérivées), alors vous comprenez -a
et -o
dans find
.
Dans la coquille,
command1 && command2
exécute la command1
et, si elle ( command1
) réussit, elle (le shell) exécute la command2
.
command1 || command2
exécute la command1
et, si elle échoue ( command1
), elle (le shell) exécute la command2
.
Dans les langues compilables,
expr1 && expr2
évalue expr1
. Si elle ( expr1
) évalue false (zéro), elle renvoie la valeur de l'expression globale. Sinon (si expr1
évalue à une valeur vraie (non nulle)), il évalue expr2
et renvoie cette valeur comme valeur de l'expression globale.
expr1 || expr2
évalue expr1
. Si elle ( expr1
) évalue une valeur vraie (non nulle), elle renvoie la valeur de l'expression globale. Sinon (si expr1
évalue false (zéro)), il évalue expr2
et renvoie cette valeur comme valeur de l'expression globale.
C'est ce que l'on appelle l'évaluation en court-circuit, car elle permet d'évaluer une expression booleanne sans évaluer les termes dont les valeurs ne sont pas nécessaires pour déterminer la valeur globale de l'expression.
Citant de find (1) ,
GNU
find
search l'arborescence des directorys enracinée à chaque nom de file en évaluant l'expression donnée de gauche à droite, selon les règles de préséance (voir section OPERATORS), jusqu'à ce que le résultat soit connu (le côté gauche est faux et les opérations, true pour ou ), à quel point lafind
passe au prochain nom de file.
⋮EXPRESSIONS
L'expression est composée de … tests (qui renvoient une valeur vraie ou fausse), et d'actions (qui ont des effets secondaires et returnnent une valeur vraie ou fausse), séparés par des opérateurs. -et est supposé là où l'opérateur est omis.
⋮La sous-section sur ACTIONS stipule que -print , comme
la plupart des actions, renvoie toujours la valeur true.⋮
LES OPÉRATEURS
⋮
expr1 expr2
expr1 -a expr2
expr1 et expr2 ⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅ Non compatible POSIXEt; expr2 n'est pas évalué si expr1 est faux.
expr1 -o expr2
expr1 ou expr2 ⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅ Non compatible POSIXOu; expr2 n'est pas évalué si expr1 est vrai.
La spécification Open Group pour find
a des choses similaires à dire:
L'utilitaire find doit redescendre récursivement la hiérarchie des directorys …, en évaluant une expression booleanne composée des primitives décrites dans la section OPERANDS pour chaque file rencontré.
⋮OPERANDS
⋮
-printingLe primaire doit toujours évaluer comme vrai; il doit faire en sorte que le path actuel soit écrit sur la sortie standard.
⋮
Les primaires peuvent être combinées en utilisant les opérateurs suivants (par ordre décroissant de priorité):
⋮expression [-a] expression
Conjonction des primaires; l'opérateur AND est impliqué par la juxtaposition de deux primitives ou rendu explicite par l'opérateur facultatif -a . La deuxième expression ne doit pas être évaluée si la première expression est fausse.
expression -o expression
Alternance des primaires; l'opérateur OR. La deuxième expression ne doit pas être évaluée si la première expression est vraie.
Les deux documents disent: "Si aucune expression n'est présente, -print doit être utilisé comme expression".
Alors,
find -type d
est équivalent à
find -type d -print
ce qui équivaut à
find -type d -a -print
ce qui signifie,
-type d
. -print
. Attendu que ,
find -print -type d
est équivalent à
find -print -a -type d
ce qui signifie,
-print
(c'est-à-dire que cela se produit pour tous les files ) . -print
), évaluez le test de -type d
. -type d
est ignoré. Donc, vous l'avez.
L'ordre des arguments de search est important. La command doit être construite comme find -type d -print0
et ensuite elle fonctionnera comme prévu. Je pensais juste que je l'afficherais au cas où cela serait utile à qui que ce soit.
L'astuce pour comprendre une command find
est d'évaluer récursivement et de regrouper les deux premières expressions / actions dans l'expression appropriée ( -false
ou -false
) de la valeur logique résultante, en considérant que l'évaluation de chaque paire d'expressions / actions est court-circuitée donc les expressions / actions en tant que second opérande d'une comparaison AND
ne seront pas évaluées et exécutées si la première expression évaluée est FALSE
et que les expressions / actions en tant que second opérande d'une comparaison OR
ne seront pas évaluées et exécutées si le premier l'expression évaluée est TRUE
) et que chaque action rencontrée au cours du process sera toujours évaluée comme TRUE
et exécutée au moment de son évaluation (si elle n'est pas ignorée par une évaluation de court-circuit) en fonction de la valeur logique de l'évaluation précédente le moment de l'évaluation déjà réduit à une expression -false
ou -false
) paire d'expressions / actions .
Élargir un exemple dans le lien utile posté par 1_CR:
find . -false -o -false -a -printf 'nope\n' -o -printf 'yep\n' -o -printf 'nope\n' yep
-false -o -false
: le premier opérande est une expression, donc aucune action n'est exécutée, et sa valeur est FALSE
; l'évaluation n'est pas court-circuitée, puisque <expr1>
est FALSE
, donc -false
est évalué et sa valeur est FALSE
; la valeur de l'expression entière est FALSE
, et est réduite à une expression -false
qui sera évaluée avec l'expression / action suivante; -false -a -printf 'nope\n'
: le premier opérande est une expression, donc aucune action n'est exécutée, et sa valeur est FALSE
; l'évaluation est court-circuitée, puisque <expr1>
est FALSE
, donc <expr2>
n'est pas évalué et n'est pas exécuté; la valeur de l'expression entière est FALSE
, et est réduite à une expression -false
qui sera évaluée avec l'expression / action suivante; -false -o -printf 'yep\n'
: le premier opérande est une expression, donc aucune action n'est exécutée, et sa valeur est FALSE
; l'évaluation n'est pas en court-circuit, puisque <expr1>
est FALSE
, donc printf 'yep\n'
est évalué et exécuté maintenant , et sa valeur est TRUE
; la valeur de l'expression entière est TRUE
, et est réduite à une expression -true
qui sera évaluée avec l'expression / action suivante; -true -o -printf 'nope\n'
: le premier opérande est une expression, donc aucune action n'est exécutée, et sa valeur est TRUE
; l'évaluation est court-circuitée, puisque <expr1>
est TRUE
, donc <expr2>
n'est pas évalué et n'est pas exécuté; la valeur de l'expression entière est TRUE
; find [...] -print0 -a -type d
(car un opérateur manquant se développe en un opérateur AND
):
-print0 -a -type d
: le premier opérande est une action, donc -print0
est évalué et exécuté maintenant , et sa valeur est TRUE
; l'évaluation n'est pas court-circuitée, puisque <expr1>
est TRUE
, le -type d
est évalué et sa valeur est TRUE
ou FALSE
; la valeur de l'expression entière est TRUE
ou FALSE
fonction du résultat du test de -type d
;