La respuesta de muru es apropiada y adecuada para casos en los que queremos imprimir algo si se encuentra el archivo. Para el caso general cuando queremos ejecutar comandos externos, como echo
, podríamos usar -exec
flag.
$ find . -name 'xac' -exec echo "I found " {} \; -quit
I found ./xac
La {}
parte pasa el nombre de archivo al comando entre -exec
y \;
como argumentos. Tenga en cuenta lo \
anterior ;
: evita que el shell lo malinterprete ; en el punto y coma que cierra el punto y coma significa el final del comando, pero cuando se escapa con una barra oblicua, el shell lo tratará como un texto literal que se pasará al find
comando y para encontrar el comando sirve como -exec
argumento de cierre .
Para construir condicionales del if found do this; else do that
tipo, podríamos hacer uso de la substición de comando $()
y el test
comando (aka [
)
$ [ "x$(find . -name 'noexist' -print -quit)" != "x" ] && echo "found" || echo "not found"
not found
$ [ "x$(find . -name 'xac' -print -quit)" != "x" ] && echo "found" || echo "not found"
found
Abordar el comentario de Dan
Dan en los comentarios preguntó:
¿No sería mejor "echo he encontrado {}" que echo "he encontrado" {}? Tal vez para echo está bien, pero si alguien copia el comando y reemplaza echo con otro comando, puede tener un problema
Vamos a entender el problema primero. Por lo general, en los shells hay un concepto de división de palabras, lo que significa que las variables no citadas y los parámetros posicionales se expandirán y tratarán como elementos separados. Por ejemplo, si usted tiene la variable var
y contiene hello world
texto, cuando lo hace touch $var
el shell dividirlo en dos artículos separados hello
y world
y touch
va a entender que, como si estuviera tratando de crear 2 archivos separados; Si lo hace touch "$var"
, Shell lo tratará hello world
como una unidad y touch
creará un solo archivo. Esto es importante para entender que esto sucede solo debido a cómo funcionan las conchas.
Por el contrario, find
no sufre ese comportamiento, ya que los comandos se procesan por find
sí mismos y se ejecutan mediante una execvp()
llamada al sistema, por lo que no hay shell involucrado. Si bien las llaves tienen un significado especial en los shells, porque aparecen en el medio del find
comando, y no al principio, no tienen un significado especial para shell en este caso. Aquí hay un ejemplo. Creemos algunos nombres de archivo difíciles e intentemos pasarlos como argumento para stat
ordenar.
$ touch with$'\t'tab.txt with$' 'space.txt with$'\n'newline.txt
$ find -type f -exec stat -c "%F" {} \; -print
regular empty file
./with?newline.txt
regular empty file
./with space.txt
regular empty file
./with?tab.txt
Como puede ver, stat
recibe nombres de archivo difíciles perfectamente bien find
, que es una de las razones principales por las que se recomienda su uso en scripts portátiles, y especialmente útil cuando atraviesa el árbol de directorios y desea hacer algo con nombres de archivo que podrían tener personajes especiales en ellos. Por lo tanto, no es necesario citar llaves para los comandos ejecutados en find
.
Es una historia diferente cuando Shell se involucra. A veces necesitas usar un shell para procesar el nombre del archivo. En ese caso, las citas realmente importan, pero es importante darse cuenta de que no es el problema del hallazgo: es el shell el que divide las palabras.
$ find -type f -exec bash -c "stat {}" sh \;
stat: cannot stat './with': No such file or directory
sh: line 1: newline.txt: command not found
stat: cannot stat './with': No such file or directory
stat: cannot stat 'space.txt': No such file or directory
stat: cannot stat './with': No such file or directory
stat: cannot stat 'tab.txt': No such file or directory
Entonces, cuando citamos dentro de Shell , funcionará. Pero de nuevo, eso es importante para Shell, no find
.
$ find -type f -exec bash -c "stat -c '%F' '{}'" sh \;
regular empty file
regular empty file
regular empty file
/some/path
le dice a encontrar dónde comenzar a buscar, pero nada le dice qué buscar. Lo mismo en tu respuesta vinculada. Lo que funciona para mí esfind /some/path -name xac -print0 -quit | grep -qz . && echo found
. ¿Me he perdido algo?