En find -exec, ¿cómo sustituir el archivo actual por {}?

En find -exec, ¿cómo sustituir el archivo actual por {}?

Quiero encontrar todos los archivos que no son de mi propiedad (es decir, que no tienen permiso para modificarlos). Yo he tratado

find . -exec if [[ ! -O {} ]]; then echo {}; fi ;

Pero si pongo el comando completo -execentre comillas, así:

find . -exec 'if [[ ! -O {} ]]; then echo {}; fi' \;

Eso tampoco funciona, porque la referencia al archivo actual {}está entre comillas y, por lo tanto, no se expande al archivo.

El problema es que no sé cómo incrustar el {}archivo actual en un archivo más complejo -execque simplemente, por ejemplo find . -exec grep smf {} \;(que se usa {}solo una vez). ¿Cómo utilizar -execla opción en los comandos de búsqueda, donde hace referencia al archivo actual más de una vez? (Eso es usar {}más tiempo).

Respuesta1

Su código no funciona porque la utilidad que solicita findejecutar ifno existe (es una palabra clave en la sintaxis del shell).

La -Oprueba es verdadera si el argumento es un archivo propiedad del usuario actual. La misma prueba se puede realizar por findsí sola con -user "$USER"(suponiendo que $USERse expanda al usuario actual):

find . -type f ! -user "$USER"

También puede utilizar test -Osi su utilidad externa testadmite esa prueba no estándar (verifique man test):

find . -type f ! -exec test -O {} \; -print

Si aún desea o necesita usar la -Oprueba integrada en el bashshell, entonces tendrá que generar un bashshell para realizar la prueba:

find . -type f -exec bash -c '[[ ! -O "$1" ]]' bash {} \; -print

Esto inicia un bash -cscript en línea para cada archivo encontrado que ejecuta la prueba en su primer argumento ( $1). El argumento se pasa en la línea de comando del script find(la bashcadena anterior {}se colocará dentro $0del script y ese shell la utilizará para mensajes de error). Si la prueba es verdadera (el archivo no es de su propiedad), -printentra en vigor e imprime la ruta del archivo.

Puedes hacer esto un poco más eficientemente con

find . -type f -exec bash -c '
    for pathname do
        [[ ! -O "$pathname" ]] && printf "%s\n" "$pathname"
    done' bash {} +

Esto es más eficiente ya que pasa lotes de nombres de rutas encontrados al bash -cscript.

... pero usar -user "$USER"sería la mejor opción.

Ver también:

información relacionada