encontrar con -execdir

15

Cuando corro findcon -execdirno obtengo los resultados que esperaba.

Por ejemplo:

mkdir -p a/b/c
find . -type d -execdir touch foo \;
$ tree a
a
├── b
   ├── c
   └── foo
└── foo

El directorio cno contiene un fooarchivo. ¿Cómo puedo findvisitar y hacer algo localmente en cada directorio?

Marcus Junius Brutus
fuente

Respuestas:

18

Para cada archivo coincidente (es decir, cada directorio), findcambia al directorio que lo contiene (es decir, su directorio padre) y ejecuta el comando especificado. Como el comando no usa el nombre de la coincidencia, nunca actuará en todos los directorios. Para este árbol de directorios en particular, estás haciendo

(cd . && touch foo)        # because ./a matches
(cd ./a && touch foo)      # because ./a/b matches
(cd ./a/b && touch foo)    # because ./a/b/c matches

Para crear un archivo en cada directorio, simplemente puede usar en -execlugar de -execdir, siempre que su implementación de findpermisos {}dentro de un argumento (la mayoría lo hace, y en particular creo que todos):

find . -type d -exec touch {}/foo +

Para la portabilidad POSIX, deberá ensamblar el nombre del directorio y el nombre base del archivo manualmente.

find . -type d -exec sh -c 'touch "$0/foo"' {} \;

o (un poco más rápido)

find . -type d -exec sh -c 'for d; do touch "$d/foo"; done' _ {} +

Alternativamente, puede usar la coincidencia de comodines recursiva de bash. Tenga en cuenta que (a diferencia de la función correspondiente en ksh y zsh, y a diferencia de su findcomando) bash se repite bajo enlaces simbólicos a los directorios.

shopt -s globstar
for d in **/*/; do touch -- "$d/foo"; done

Una solución zsh:

touch ./**/(e\''REPLY+=foo'\')
Gilles 'SO- deja de ser malvado'
fuente
FYI: man bashestados bajo "-c": los argumentos después de command_string se asignan a los parámetros posicionales que comienzan con $ 0, sin embargo, "for d" iterará a través de los parámetros posicionales que comienzan con $ 1. "_" es texto asignado a $ 0 y no se utilizará.
Chad Skeeters
3

El comando se ejecuta en cada directorio que contiene un archivo coincidente. Como cno contiene un directorio, no coincide y, por lo tanto, no se ejecutará allí.

La solución es agregar el nombre del directorio al argumento execdir, así:

find . -type d -execdir touch {}/foo \;
Jenny D
fuente
2

Desde man file

   -execdir command {} +
          Like  -exec,  but  the  specified  command is run from the subdirectory containing the matched file

Su directorio coincidente cvive en el bdirectorio, de modo que es donde se ejecuta el ejecutivo. Funcionaría como espera si busca archivos en lugar de directorios.

Probablemente podría lograr lo que desea enviando los directorios, xargsya que se le proporcionará la lista completa de directorios.

Mate
fuente