C'è un modo per elencare una serie di 30 file casuali da una directory usando i comandi standard di Linux? (in zsh
)
La risposta migliore qui descritta non funziona per me ( sort
non riconosce l'opzione -R
)
C'è un modo per elencare una serie di 30 file casuali da una directory usando i comandi standard di Linux? (in zsh
)
La risposta migliore qui descritta non funziona per me ( sort
non riconosce l'opzione -R
)
Risposte:
Dato che stai citando zsh:
rand() REPLY=$RANDOM
print -rl -- *(o+rand[1,30])
È possibile sostituire print
con dire ogg123
e *
con dire**/*.ogg
Prova a collegare l' ls
output a shuf
, ad es
$ touch 1 2 3 4 5 6 7 8 9 0
$ ls | shuf -n 5
5
9
0
8
1
Il -n
flag specifica quanti file casuali vuoi.
command not found
(non installato): /
ls
.
È abbastanza facile risolverlo con un po 'di Perl. Seleziona quattro file a caso dalla directory corrente:
perl -MList::Util=shuffle -e 'print shuffle(`ls`)' | head -n 4
Per l'uso in produzione, però, andrei con uno script espanso che non si basa ls
sull'output, può accettare qualsiasi directory, controllare i tuoi argomenti, ecc. Nota che la selezione casuale stessa è ancora solo un paio di righe.
#!/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
) non era sufficiente per il PO. Quanto a ciò che è e non è lo standard Unix: il Perl esiste ovunque e risolve il problema in modo succinto e solido. Se avessi dato questo come un one-liner Perl, sarebbe stato considerato come "riga di comando"? Il fatto che Perl sia potente è davvero un argomento contro l'esistenza di questa risposta?
perl -MList::Util=shuffle -e 'print shuffle(
ls )' | head -n 4
È questo più simile a quello che cercavi?
Una soluzione semplice che evita l'analisi di ls e funziona anche con gli spazi:
shuf -en 30 dir/* | while read file; do
echo $file
done
shuf
.
shuf
non è menzionato nella domanda. Questa risposta sarà comunque utile ad altri utenti.
Un oneliner che non usa altro che Zsh:
files=(*); for x in {1..30}; do i=$((RANDOM % ${#files[@]} + 1)); echo "${files[i]}"; done
Lo stesso in Bash, dove gli indici di array sono a base zero:
files=(*); for x in {1..30}; do i=$((RANDOM % ${#files[@]})); echo "${files[i]}"; done
Si noti che nessuna versione prende in considerazione i duplicati.