Lista de arquivos aleatórios X de um diretório

11

Existe uma maneira de listar um conjunto de 30 arquivos aleatórios de um diretório usando comandos padrão do Linux? (em zsh )

A principal resposta descrita aqui não funciona para mim ( sort não reconhece a opção -R )

    
por Amelio Vazquez-Reina 18.09.2012 / 04:18

5 respostas

6

Desde que você mencionou o zsh:

rand() REPLY=$RANDOM
print -rl -- *(o+rand[1,30])

Você pode substituir print com ogg123 e * com **/*.ogg

    
por 18.09.2012 / 08:25
16

Tente colocar a saída ls em shuf , por exemplo

$ touch 1 2 3 4 5 6 7 8 9 0
$ ls | shuf -n 5
5
9
0 
8
1

O sinalizador -n especifica quantos arquivos aleatórios você deseja.

    
por 18.09.2012 / 04:22
2

É muito fácil resolver isso com um pouquinho de Perl. Selecione quatro arquivos aleatoriamente no diretório atual:

perl -MList::Util=shuffle -e 'print shuffle('ls')' | head -n 4

Para uso em produção, eu usaria um script expandido que não dependesse de ls output, pudesse aceitar qualquer dir, verificasse seus args, etc. Observe que a própria seleção aleatória ainda é apenas um par de linhas .

#!/usr/bin/perl    
use strict;
use warnings;
use List::Util qw( shuffle );

if ( @ARGV < 2 ) {
    die "$0 - List n random files from a directory\n"
        . "Usage: perl $0 n dir\n";
}
my $n_random = shift;
my $dir_name = shift;
opendir(my $dh, $dir_name) || die "Can't open directory $dir_name: $!";

# Read in the filenames in the directory, skipping '.' and '..'
my @filenames = grep { !/^[.]{1,2}$/ } readdir($dh);
closedir $dh;

# Handle over-specified input
if ( $n_random > $#filenames ) {
    print "WARNING: More values requested ($n_random) than available files ("
          . @filenames . ") - truncating list\n";
    $n_random = @filenames;
}

# Randomise, extract and print the chosen filenames
foreach my $selected ( (shuffle(@filenames))[0..$n_random-1] ) {
    print "$selected\n";
}
    
por 18.09.2012 / 06:50
1

Uma solução simples que evita a análise de ls e também funciona com espaços:

shuf -en 30 dir/* | while read file; do
    echo $file
done
    
por 30.08.2017 / 10:19
0

Um oneliner usando nada além de Zsh:

files=(*); for x in {1..30}; do i=$((RANDOM % ${#files[@]} + 1)); echo "${files[i]}"; done

O mesmo no Bash, onde os índices de array são baseados em zero:

files=(*); for x in {1..30}; do i=$((RANDOM % ${#files[@]})); echo "${files[i]}"; done

Note que nenhuma das versões leva em consideração duplicatas.

    
por 18.09.2012 / 17:51

Tags