
Me gustaría abrir un archivo seleccionado al azar a través de la terminal. Encontré shuf
, que parece ser justo la utilidad que necesito, aunque no puedo encontrar una manera de hacer que el comando con el que estoy trabajando sea recursivo.
Inicialmente usé open $(ls | gshuf -n1)
, que funciona muy bien si tengo una estructura de directorios plana. ¿Cómo puedo hacer que esto se repita en cualquier número de subdirectorios y filtrar archivos como .DS_Store
carpetas?
Respuesta1
- no analizar
ls
. - Cotizar correctamente(a menos que sepa que su shell soluciona esto, por ejemplo
zsh
).
La herramienta adecuada es find
. Funciona de forma recursiva, esto resuelve tu problema principal. Puedes excluir varios patrones si sabes cómo.
El uso básico será como:
open "$(find . -type f | shuf -n1)"
Las nuevas líneas en los nombres de archivos romperán esto. Sus herramientas pueden o no admitir opciones que no sean POSIX que permitan pasar datos terminados en NUL. Este fragmento funciona en mi Debian:
find . -type f -print0 | shuf -z -n1
aunque si lo incrustas en $(…)
, las nuevas líneas finales (si las hay) se eliminarán.
Para excluir nombres, puede usar una sintaxis como ! -name .DS_Store
, pero para excluir subdirectorios completos necesita-prune
. Hay trampas:
- El orden de los operandos importa, por ejemplo,
-prune
para un directorio debe estar antes-type f
,-print
/-print0
normalmente pertenece al final. - "o" lógico (
-o
)a menudo requiere paréntesisy no es tan intuitivo como desearías. - Omitir
-print
/-print0
puede darle más resultados de los esperados. Con lógica compleja es bueno incluir explícitamente-print
/-print0
.
Estudie man 1 find
para aprender más. Este es un ejemplo práctico que excluye dos directorios y dos patrones de nombres:
find . \( -name dir1 -o -name "dir 2" \) -prune -o -type f ! \( -name "*.txt" -o -name "echo*" \) -print
Dado que necesita $(…)
y le dije que cite correctamente, debe saber que las comillas internas $(…)
se analizan por separado. Por ejemplo, esto está correctamente citado:
open "$(find . -type f ! -name "not this file" | shuf -n1)"
(compararesta respuesta, peculiaridad 2).