¿Por qué GNU find -execdir command se comporta de forma diferente que BSD find?

En mi OSX, he instalado GNU find lado de BSD pnetworkingeterminado find via: brew install findutils .

Por lo que tengo entendido, BSD find sigue los estándares POSIX y GNU lo hace opcional (según esta publicación ), lo que genera muchas inconsistencias en el resultado esperado.

Por ejemplo:

BSD encuentra

 $ find -L /etc -execdir echo {} ';' | head etc AFP.conf afpovertcp.cfg aliases aliases.db apache2 extra httpd-autoindex.conf httpd-dav.conf httpd-default.conf 

GNU encuentra

 $ gfind --version find (GNU findutils) 4.4.2 $ POSIXLY_CORRECT=1 gfind -L /etc -execdir echo {} ';' | head /etc /etc/AFP.conf /etc/afpovertcp.cfg /etc/aliases /etc/aliases.db /etc/apache2 /etc/apache2/extra /etc/apache2/extra/httpd-autoindex.conf /etc/apache2/extra/httpd-dav.conf /etc/apache2/extra/httpd-default.conf gfind: `echo' terminated by signal 13 gfind: `echo' terminated by signal 13 ... endless loop here 

Nota: Estoy usando -L arriba ya que mi /etc es un enlace a private/etc

En GNU find manual puedo ver que puedo especificar POSIXLY_CORRECT para seguir el estándar POSIX, sin embargo, esto no funciona para el ejemplo anterior.

¿Alguna otra forma de forzar el mismo resultado (por ejemplo, el estándar POSIX) para GNU find para el ejemplo anterior?

Además de bucle continuo, ¿por qué GNU imprime nombres de file relativos y BSD imprime routes completas en su lugar?

No se trata de un bucle infinito , es solo que GNU find que el echo murió a causa de un SIGPIPE (porque el otro extremo de la tubería en stdout se cerró cuando se murió la head ).

-execdir no está especificado por POSIX. E incluso para -exec , no hay nada en la especificación POSIX que diga que si el command es aniquilado por un SIGPIPE, find debería salir.

Entonces, ¿POSIX especificará -execdir , gfind probablemente sea más conforme a POSIX que tu BSD find (suponiendo que tu BSD encuentre salidas en su hijo que muere de un SIGPIPE como sugiere la networkingacción de tu pregunta, FreeBSD no lo encuentra en mis testings y lo hace ejecutar echo en un bucle para cada file (como para GNU find, no infinito)).

Puede decir que, para la mayoría de los casos comunes, sería preferible salir de un niño muriendo de SIGPIPE, pero el command -exec aún podría morir de un SIGPIPE por otras razones que la tubería de stdout se cerró, por lo que salir de find para eso estar en el límite aceptable.

Con GNU find , puede decirle a find para salir si un command falla con:

 find . ... \( -exec echo {} \; -o -quit \) 

En cuanto a si está permitida o prohibida la implementación de un find para informar a los niños que mueren de una señal en stderr, aquí (con el uso de -execdir ) estamos fuera del scope de POSIX de todos modos, pero si se utilizó -exec en lugar de -execdir , parece que sería un caso donde gfind no está de acuerdo.

La especificación para find dice: "el error estándar se usará solo para posts de diagnóstico", pero también dice :

Comportamiento pnetworkingeterminado: cuando esta sección se enumera como "El error estándar se utilizará solo para posts de diagnóstico", significa que, a less que se indique lo contrario, los posts de diagnóstico se enviarán al error estándar solo cuando el estado de salida indique que un error ocurrido y la utilidad se usa como se describe en este volumen de POSIX.1-2008.

Lo que indicaría que dado que find no retorna con un estado de salida distinto de cero en ese caso, no debería generar ese post en stderr.

Tenga en count que, según ese text, tanto GNU como FreeBSD find no cumplir en un caso como el siguiente:

 $ find /dev/null -exec blah \;; echo "$?" find: `blah': No such file or directory 0 

donde ambos informan un error sin establecer el estado de salida en un valor distinto de cero. Por eso planteé la cuestión en la list de correo de austin-group (los chicos detrás de POSIX) .

Tenga en count que si cambia su command a:

 (trap '' PIPE; find -L /etc -execdir echo {} \; | head) 

echo aún se ejecutará para cada file, todavía fallará, pero esta vez, será echo informando el post de error.


Ahora se muestra el filename de filename vs /etc/filename vs ./filename .

Una vez más, -execdir no es una opción estándar , no hay text que diga quién tiene la razón y quién está equivocado. -execdir fue introducido por BSD find y copydo más tarde por GNU find .

GNU find ha realizado algunos cambios intencionados (mejoras) sobre él. Por ejemplo, antepone los nombres de file con ./ en los arguments pasados ​​a los commands. Eso significa que find . -execdir cmd {} \; find . -execdir cmd {} \; no tiene un problema con los nombres de file que comienzan con - por ejemplo.

El hecho de que -L -execdir no pase una -L -execdir file relativa al directory padre es en realidad un error que afecta a la versión 4.3.0 a 4.5.8 de GNU find . Se arregló en la 4.5.9, pero eso está en la twig de desarrollo y no ha habido una nueva versión estable desde (hasta el 12/12/2015, aunque una es inminente ).

Más información en la list de correo de findutils .

Si todo lo que desea es imprimir el nombre base de cada file en /etc portátil, puede hacer lo siguiente:

 find -L /etc -exec basename {} \; 

O más eficientemente:

 find -L ///etc | awk -F / '/\/\// && NR>1 {print last} {if (NF > 1) last = $NF else last = last "\n" $NF} END {if (NR) print last}' 

que puedes simplificar a

 find -L /etc | awk -F / '{print $NF}' 

si puede garantizar que las routes de files no contengan caracteres de nueva línea (IIRC, algunas versiones de OS / X tenían tales files en / etc).

GNUly:

 find -L /etc -printf '%f\n' 

En cuanto a si:

 find -exec echo {} \; 

en el enlace al que se refiere, es POSIX o no.

No, como una invocación de command, eso no es POSIX. Una secuencia de commands que tendría que sería no conforme.

POSIX find requiere que se proporcione al less una ruta, pero deja el comportamiento no especificado si el primer argumento de find no opcional comienza con - o es un pnetworkingicado de find (como ! O ( ), para que el comportamiento de find GNU sea compatible, por lo tanto implementaciones que informan un error (o tratan el primer argumento como una ruta de file incluso si representa un pnetworkingicado de búsqueda) o rocían pintura roja en su cara, no hay ninguna razón por la cual POSIXLY_CORRECT afecte el comportamiento de find allí.