Quiero saber exactamente qué {} \;
y {} \+
y | xargs ...
hacer. Por favor aclare estos con explicaciones.
Los siguientes 3 comandos se ejecutan y generan el mismo resultado, pero el primer comando toma un poco de tiempo y el formato también es un poco diferente.
find . -type f -exec file {} \;
find . -type f -exec file {} \+
find . -type f | xargs file
Es porque el primero ejecuta el file
comando para cada archivo que proviene del find
comando. Entonces, básicamente se ejecuta como:
file file1.txt
file file2.txt
Pero los últimos 2 encuentran con los -exec
comandos ejecutar el comando de archivo una vez para todos los archivos como se muestra a continuación:
file file1.txt file2.txt
Luego ejecuto los siguientes comandos en los que el primero se ejecuta sin problema, pero el segundo da un mensaje de error.
find . -type f -iname '*.cpp' -exec mv {} ./test/ \;
find . -type f -iname '*.cpp' -exec mv {} ./test/ \+ #gives error:find: missing argument to `-exec'
Para el comando con {} \+
, me da el mensaje de error.
find: missing argument to `-exec'
¿porqué es eso? ¿Alguien puede explicar qué estoy haciendo mal?
Respuestas:
La página del manual (o el manual GNU en línea ) explica prácticamente todo.
buscar comando -exec {} \;
Para cada resultado,
command {}
se ejecuta. Todas las apariciones de{}
son reemplazadas por el nombre del archivo.;
tiene como prefijo una barra inclinada para evitar que el shell lo interprete.buscar comando -exec {} +
Cada resultado se agrega
command
y se ejecuta posteriormente. Teniendo en cuenta las limitaciones de longitud del comando, supongo que este comando se puede ejecutar más veces, con la página del manual apoyándome:Tenga en cuenta esta cita de la página del manual:
Es por eso que no se permiten caracteres entre
{}
y+
excepto espacios en blanco.+
hace que find detecte que los argumentos deben agregarse al comando comoxargs
.La solución
Afortunadamente, la implementación de GNU de
mv
puede aceptar el directorio de destino como argumento, con-t
el parámetro más largo o con uno--target
. Su uso será:Tu
find
comando se convierte en:Desde la página del manual:
fuente
./test/
entre{}
y+
, pero no se permiten caracteres que no sean espacios en blanco entre estos.+
comando AFAIU es un poco extraño ya que pega los archivos al "final" (y no en lugar de{}
), así que ¿por qué usarlo{}
? Esto es confuso. Gracias por la-t
opción que no conocía, ¡parece que esa opción se creó como una solución a ese-exec +
problema!Encontré el mismo problema en Mac OSX , usando un shell ZSH : en este caso no hay
-t
opciónmv
, así que tuve que encontrar otra solución. Sin embargo, el siguiente comando tuvo éxito:El secreto fue citar los frenos . No es necesario que las llaves estén al final del
exec
comando.Probé en Ubuntu 14.04 (con shells BASH y ZSH ), funciona igual.
Sin embargo, cuando se usa el
+
signo, parece que tiene que estar al final delexec
comando.fuente
{}
debe citarse en las conchasfish
yrc
, pero no enzsh
,bash
ni en ninguna otra concha de las familias Bourne o csh.bash
, de hecho, las comillas no son necesarias. Curiosamente, tuve un problema si no los citaba en MacOS (usandozsh
). Pero no tengo una Mac al alcance para intentarlo de nuevo ...El equivalente estándar de
find -iname ... -exec mv -t dest {} +
parafind
implementaciones que no son compatibles-iname
omv
implementaciones que no son compatibles-t
es usar un shell para reordenar los argumentos:Al usar
-name '*.[cC][pP][pP]'
, también evitamos depender de la configuración regional actual para decidir cuál es la versión en mayúsculas dec
op
.Tenga en cuenta que
+
, al contrario que;
no es especial en ningún shell, por lo que no es necesario citarlo (aunque citar no hará daño, excepto, por supuesto, con shells comorc
ese que no se admiten\
como operador de comillas).El arrastre
/
en/dest/dir/
es para quemv
falla con un error en lugar de cambiar el nombrefoo.cpp
a/dest/dir
en el caso en el que sólo unacpp
se encontró archivo y/dest/dir
no existe o no es un directorio (o enlace simbólico al directorio).fuente
fuente
no, la diferencia entre
+
y\;
debe invertirse.+
agrega los archivos al final del comando exec, luego ejecuta el comando exec y\;
ejecuta el comando para cada archivo.El problema es
find . -type f -iname '*.cpp' -exec mv {} ./test/ \+
quefind . -type f -iname '*.cpp' -exec mv {} ./test/ +
no debería ser necesario escapar de él o terminar el+
xargs no he usado en mucho tiempo, pero creo que funciona como +.
fuente
-name "*.cpp"
Casi no uso -iname a menos que quiera hacer una búsqueda de expresiones regulares difícil, como -iname '??? work. * \. Cpp'-iname
y-name
.-iname
es la versión que no distingue entre mayúsculas y minúsculas-name
y no tiene diferencias en el manejo de las expresiones regulares. Sugiero probar los comandos antes de publicar, su comando también falla en mi shell.