Existe uma maneira de listar um conjunto de, digamos, 30 arquivos aleatórios de um diretório usando comandos padrão do Linux? (in zsh
)
A resposta principal descrita aqui não funciona para mim ( sort
não reconhece a opção -R
)
Existe uma maneira de listar um conjunto de, digamos, 30 arquivos aleatórios de um diretório usando comandos padrão do Linux? (in zsh
)
A resposta principal descrita aqui não funciona para mim ( sort
não reconhece a opção -R
)
Respostas:
Desde que você está mencionando zsh:
rand() REPLY=$RANDOM
print -rl -- *(o+rand[1,30])
Você pode substituir print
por dizer ogg123
e *
dizer**/*.ogg
Tente canalizar a ls
saída para shuf
, por exemplo
$ touch 1 2 3 4 5 6 7 8 9 0
$ ls | shuf -n 5
5
9
0
8
1
O -n
sinalizador especifica quantos arquivos aleatórios você deseja.
command not found
(não instalado): /
ls
.
É 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
No entanto, para uso em produção, eu usaria um script expandido que não depende da ls
saída, pode aceitar qualquer dir, verifica seus argumentos, etc. Observe que a seleção aleatória em si ainda tem apenas algumas 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";
}
shuf
) não era suficiente para o OP. Quanto ao que é e não é padrão, o Unix - Perl existe em todos os lugares e resolve o problema de maneira sucinta e robusta. Se eu tivesse dado isso como uma linha única do Perl, isso contaria como 'linha de comando'? O fato de Perl ser poderoso é realmente um argumento contra a existência dessa resposta?
perl -MList::Util=shuffle -e 'print shuffle(
ls )' | head -n 4
É mais parecido com o que você estava procurando?
Uma solução simples que evita a análise de ls e também trabalha com espaços:
shuf -en 30 dir/* | while read file; do
echo $file
done
shuf
.
shuf
não é mencionado na pergunta. Esta resposta ainda será útil para outros usuários.
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 da matriz são baseados em zero:
files=(*); for x in {1..30}; do i=$((RANDOM % ${#files[@]})); echo "${files[i]}"; done
Observe que nenhuma das versões leva em consideração as duplicatas.