Estoy intentando utilizar el find
comando para enumerar el tamaño de un determinado conjunto de archivos, pero no obtengo ningún resultado. El comando que uso es:
find POD -type f -name *.mp3 -or -name *.ogg -ls
Lo que no produce ningún resultado. Mientras:
find POD -type f -name *.mp3 -or -name *.ogg
produce resultados, también probé las acciones:
-printf "%p %k KB\n"
-exec ls -ls '{}' \;
-print0
pero todos estos no dan resultados. Cuando uso cualquiera de estas acciones con una expresión diferente, por ejemplo:
find . -maxdepth 1 -type f -printf "%p %k KB\n"
También obtengo el resultado esperado. ¿Alguien tiene alguna idea de cuál es el problema? Estoy corriendo:
Linux irimi 3.10.37-1-MANJARO #1 SMP Mon Apr 14 20:56:29 UTC 2014 x86_64 GNU/Linux
también conocido como una distribución actualizada de Manjaro Linux. El shell que uso es: /bin/bash
versión 4.3.8(1)-release
.
El contenido de mi SHELLOPTS
variable de entorno es:
braceexpand:emacs:hashall:histexpand:history:interactive-comments:monitor
mi BASHOPTS
variable de entorno es:
cdspell:checkwinsize:cmdhist:complete_fullquote:dotglob:expand_aliases:extglob:extquote:force_fignore:histappend:hostcomplete:interactive_comments:nocaseglob:progcomp:promptvars:sourcepath
Nuevamente, cualquier ayuda para intentar depurar esto sería muy apreciada.
Respuesta1
Hay una trampa con ely/opalabras clave en find
. or
aplicado a todos los siguientes parámetros, incluida la acción ( -ls
en su ejemplo). and
Las expresiones sin or
(o adjuntas con and
) se evalúan en orden de lectura con una parada final como falsa. No hay implicit ()
.
Entonces el comando find POD -type f -name *.mp3 -or -name *.ogg -ls
significa,
- buscar archivos (comenzando desde el directorio POD) --- si no se encuentra ningún archivo: DETENER
- de lo contrario (archivo encontrado) verifique la coincidencia del patrón
*.mp3
--- si el patrón coincide: ¡DETÉNGASE! (porqueOR
se aplica desde aquí y solo si el comando anterior falló (pero solo el comando anterior, no los grupos de comandos anteriores)
y debido a que agrega una declaración de ejecución ( -ls
,, ....) en la línea de comando -exec
, -print
no hay ningún -print
comando implícito y, por lo tanto, no hay nada que ejecutar si 1) todas las condiciones de 1) son verdaderas (el archivo y el patrón coinciden). Si elimina el último, -ls
habrá un implícito -print
distribuido al final de cada rama de condición.
- de lo contrario, si el patrón no coincide, busque nada (archivo/directorio) que coincida con el patrón
*.ogg
y enumérelos (-ls
no es un comando de condición, se ejecuta solo si el comando/prueba anterior "patrón*.ogg
es verdadero). Pero debido a 1), 2) se evalúa solo para archivos que NO sean mp3. Si no tiene.ogg
archivos, no verá nada.
Solución 1 repetir el comando de ejecución en cada rama lógica
find POD -type f -name "*.mp3" -ls -or -name "*.ogg" -ls
Solución 2agregar paréntesis (protegido por shell)
find POD -type f \( -name "*.mp3" -ls -or -name "*.ogg" \) -ls
Nota debe proteger los patrones para evitar la evaluación de patrones de shell en el directorio actual.
Respuesta2
Creo que se debe al orden de evaluación (falta de precedencia explícita), por ejemplo, si
-name '*.mp3' -o -name '*.ogg' -ls
luego, si -name '*.ogg'
se evalúa como falso, la ls
acción no se ejecuta. Puede obtener el comportamiento esperado agrupando sus expresiones OR usando paréntesis; por ejemplo, si
$ ls tests
file1.mp3 file2.mp3 file3.mp3
Entonces
$ find tests \( -name '*.mp3' -o -name '*.ogg' \) -print
tests/file3.mp3
tests/file1.mp3
tests/file2.mp3
mientras
$ find tests -name '*.mp3' -o -name '*.ogg' -print
no produce ninguna salida. Tenga en cuenta que
$ find tests -name '*.mp3' -o -name '*.ogg'
es un caso especial porque implícitamente se trata como
$ find tests \( -name '*.mp3' -o -name '*.ogg' \) -print
También tenga en cuenta que es una buena práctica citar o escapar de los globos del shell en un find
comando para evitar que el shell los expanda; consulte la NON-BUGS
sección de la página de manual de búsqueda.