Solo estaba tratando de enumerar todos los directorios y archivos en el directorio actual y también escribir si son archivos o directorios con el siguiente comando:
find -exec echo `echo {} : ;if [ -f {} ]; then echo file; else echo directory;fi` \;
Sé que es un comando tonto, puedo usar otras cosas como -type f
o -type d
, pero quiero saber por qué ese código no funcionó como esperaba. Simplemente imprime el directorio a todos ellos. Por ejemplo, mientras que la salida de find
es:
.
./dir
./dir/file
La salida de mi código es:
. : directory
./dir : directory
./dir/file : directory
Y salida de
echo `echo dir/file : ;if [ -f dir/file ]; then echo file; else echo directory;fi`
es
dir/file : file
Estoy trabajando Ubuntu 14.10
y usandofind (GNU findutils) 4.4.2
bash
shell
find
command-substitution
Esref
fuente
fuente
find -exec bash -c 'echo -n "{} : ";if [ -f "{}" ]; then echo file; else echo directory;fi' \;
"{}"
. ¿Por qué usasecho
dos veces?echo "{}" : ;if [ -f "{}" ]; then echo file; else echo directory;fi
\;Respuestas:
Primero, tu fragmento ejecuta el comando
porque necesita su salida para evaluar la sustitución del comando. Como no hay nombre de archivo
{}
, esto produce la salidaA continuación, el
find
comando se ejecuta con los argumentos-exec
,echo
,{}
,:
,directory
, por lo que para cada archivo, imprime el nombre del archivo seguido de un espacio y: directory
.Lo que realmente quiere hacer es ejecutar el fragmento de shell
echo {} :; …
en cada archivo encontrado porfind
. Este fragmento debe ser ejecutado por un shell generadofind
, no por el shell que se iniciafind
, ya que está recibiendo datos defind
su línea de comando. Por lo tanto, debe instruirfind
para ejecutar un shell:Esto es mejor, pero aún no está bien. Funcionará con algunas (no todas)
find
implementaciones si los nombres de sus archivos no contienen caracteres especiales, pero dado que está interpolando el nombre del archivo en un script de shell, permite que los nombres de archivo ejecuten comandos de shell arbitrarios, por ejemplo, si tiene un archivo llamado$(rm -rf /)
entoncesrm -rf /
se ejecutará el comando . Para pasar nombres de archivo al script, páselos como argumentos separados.También el primero
echo
imprime una nueva línea después de los dos puntos. Useecho -n
(si su shell lo admite) oprintf
para evitar esto.Puede usar
-exec … {} +
para agrupar invocaciones de shell, que es más rápido.fuente
Otra forma de ejecutar
if; then; else; fi
junto confind
es:fuente