
Gostaria de abrir um arquivo selecionado aleatoriamente através do terminal. Eu encontrei shuf
, que parece ser exatamente o utilitário que eu preciso, embora não consiga descobrir uma maneira de tornar recursivo o comando com o qual estou trabalhando.
Inicialmente usei o open $(ls | gshuf -n1)
, que funciona muito bem se eu tiver uma estrutura de diretórios simples. Como posso fazer esse recurso em qualquer número de subdiretórios e filtrar arquivos como .DS_Store
e pastas?
Responder1
- Não analise
ls
. - Cite corretamente(a menos que você saiba que seu shell corrige isso, por exemplo
zsh
).
A ferramenta certa é find
. Funciona de forma recursiva, isso resolve seu problema principal. Você pode excluir vários padrões se souber como.
O uso básico será como:
open "$(find . -type f | shuf -n1)"
Novas linhas nos nomes dos arquivos quebrarão isso. Suas ferramentas podem ou não suportar opções não POSIX que permitem a passagem de dados terminados em NUL. Este trecho funciona no meu Debian:
find . -type f -print0 | shuf -z -n1
embora se você incorporá-lo $(…)
, as novas linhas finais (se houver) ainda serão removidas.
Para excluir nomes você pode usar sintaxe como ! -name .DS_Store
, mas para excluir subdiretórios inteiros você precisa-prune
. Existem armadilhas:
- A ordem dos operandos é importante, por exemplo,
-prune
para um diretório deve estar antes de-type f
,-print
/-print0
geralmente pertence ao final. - Lógico "ou" (
-o
)muitas vezes requer parêntesese não é tão intuitivo quanto você deseja. - Omitir
-print
/-print0
pode dar mais resultados do que você espera. Com lógica complexa, é bom incluir explicitamente-print
/-print0
.
Estude man 1 find
para aprender mais. Este é um exemplo prático que exclui dois diretórios e dois padrões de nomes:
find . \( -name dir1 -o -name "dir 2" \) -prune -o -type f ! \( -name "*.txt" -o -name "echo*" \) -print
Já que você precisa $(…)
e eu disse para você citar corretamente, você deve saber que as aspas internas $(…)
são analisadas separadamente. Por exemplo, isso está devidamente citado:
open "$(find . -type f ! -name "not this file" | shuf -n1)"
(compararesta resposta, peculiaridade 2).