Eu tenho um diretório que contém centenas de milhares de arquivos.
Preciso listar amostras desses arquivos (exemplo 10 arquivos), sem processar todos os arquivos encontrados no diretório, o que levará muito tempo de processamento.
Responder1
Eu não acho que você possa obter amostras de toda a lista de arquivos sem lê-los todos de uma forma ou de outra, mesmo no nível do sistema de arquivos.
A menos queseus nomes seguem um padrão (por exemplo, fileXXXXXXX); nesse caso, você pode pré-gerar uma lista aleatória de nomes antes de acessar os arquivos. Para uma quantidade tão grande de arquivos seria estranho se seus nomes fossem aleatórios.
Mas vamos supor que você não tenha essa sorte. Using find
é preferível a ls
, pois pode escapar da saída com null, tornando-o imune a caracteres não padrão em nomes de arquivos. Se não quisermos ler todos os arquivos, o mais rápido é usar os que estão no início da listagem. Para obter uma amostra melhor, eu usaria primeiro uma amostra maior ( $oversamplesize
abaixo) e depois faria uma subseleção aleatória de tamanho $samplesize
a partir daí. Não consegui fazer sort -R
ou shuf
trabalhar bem com separadores nulos, então o embaralhamento e a seleção final são feitos por awk
:
find ~ -type f -print0 |
grep --null --null-data -m ${oversamplesize:-100} . |
awk -v samplesize=${oversamplesize:-11} -vRS='\0' -vORS='\0' \
'{ a[NR]=$0 } END {srand(); while (i<samplesize) { b=(int(rand()*10000)%samplesize); if (b in c) {continue;} else {c[b]=a[b]; print a[b]; i++;} }; }' |
xargs -0 echo # echo here being just a dummy
Duas notas aqui. Por alguma razão, muitas vezes também imprime um nome de arquivo vazio, então aumentei o tamanho da amostra para garantir. A nota trivial é não esquecer de alterar o caminho de pesquisa (~ aqui) e o comando final.