¿Hay alguna manera de enumerar un conjunto de, digamos, 30 archivos aleatorios de un directorio utilizando comandos estándar de Linux? (en zsh
)
La respuesta principal descrita aquí no funciona para mí ( sort
no reconoce la opción -R
)
¿Hay alguna manera de enumerar un conjunto de, digamos, 30 archivos aleatorios de un directorio utilizando comandos estándar de Linux? (en zsh
)
La respuesta principal descrita aquí no funciona para mí ( sort
no reconoce la opción -R
)
Respuestas:
Como mencionas zsh:
rand() REPLY=$RANDOM
print -rl -- *(o+rand[1,30])
Puede reemplazar print
con say ogg123
y *
con say**/*.ogg
Intente canalizar la ls
salida a shuf
, p. Ej.
$ touch 1 2 3 4 5 6 7 8 9 0
$ ls | shuf -n 5
5
9
0
8
1
La -n
bandera especifica cuántos archivos aleatorios desea.
command not found
(no instalado): /
ls
.
Es bastante fácil resolver esto con un poquito de Perl. Seleccione cuatro archivos al azar del directorio actual:
perl -MList::Util=shuffle -e 'print shuffle(`ls`)' | head -n 4
Sin embargo, para uso en producción, iría con un script expandido que no depende de la ls
salida, puede aceptar cualquier directorio, verifica sus argumentos, etc. Tenga en cuenta que la selección aleatoria en sí misma solo es un par de líneas.
#!/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
) no era suficiente para el OP. En cuanto a qué es y qué no es Unix estándar, Perl existe en todas partes y resuelve el problema de manera sucinta y sólida. Si hubiera dado esto como una línea Perl, ¿eso habría contado como 'línea de comando'? ¿Es el hecho de que Perl es poderoso realmente un argumento en contra de la existencia de esta respuesta?
perl -MList::Util=shuffle -e 'print shuffle(
ls )' | head -n 4
¿Se parece más a lo que estabas buscando?
Una solución simple que evita el análisis de ls y también funciona con espacios:
shuf -en 30 dir/* | while read file; do
echo $file
done
shuf
.
shuf
no se menciona en la pregunta. Esta respuesta seguirá siendo útil para otros usuarios.
Un oneliner que usa nada más que Zsh:
files=(*); for x in {1..30}; do i=$((RANDOM % ${#files[@]} + 1)); echo "${files[i]}"; done
Lo mismo en Bash, donde los índices de matriz están basados en cero:
files=(*); for x in {1..30}; do i=$((RANDOM % ${#files[@]})); echo "${files[i]}"; done
Tenga en cuenta que ninguna de las versiones tiene en cuenta los duplicados.