Is there a way to list a set of say, 30 random files from a directory using standard Linux commands? (in zsh)
The top answer described here does not work for me (sort does not recognize the option -R)
Is there a way to list a set of say, 30 random files from a directory using standard Linux commands? (in zsh)
The top answer described here does not work for me (sort does not recognize the option -R)
Try piping the ls output to shuf, e.g.
$ touch 1 2 3 4 5 6 7 8 9 0
$ ls | shuf -n 5
5
9
0
8
1
The -n flag specifies how many random files you want.
command not found (not installed) :/
ls.
Since you're mentioning zsh:
rand() REPLY=$RANDOM
print -rl -- *(o+rand[1,30])
You can replace print with say ogg123 and * with say **/*.ogg
A simple solution that avoids parsing of ls and also works with spaces:
shuf -en 30 dir/* | while read file; do
echo $file
done
shuf.
shuf isn't mentioned in the question. This answer will still be helpful to other users.
It's quite easy to solve this with a tiny bit of Perl. Select four files at random from the current directory:
perl -MList::Util=shuffle -e 'print shuffle(`ls`)' | head -n 4
For production use though, I would go with an expanded script that doesn't rely on ls output, can accept any dir, checks your args, etc. Note that the random selection itself is still only a couple of lines.
#!/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) was not sufficient for the OP. As to what is and isn't standard Unix - Perl exists everywhere, and it solves the problem succinctly and robustly. If I'd given this as a Perl one-liner, would that have counted as 'command line'? Is the fact Perl is powerful really an argument against the existence of this answer?
perl -MList::Util=shuffle -e 'print shuffle(ls)' | head -n 4 Is this more like what you were looking for?
A oneliner using nothing but Zsh:
files=(*); for x in {1..30}; do i=$((RANDOM % ${#files[@]} + 1)); echo "${files[i]}"; done
The same in Bash, where array indices are zero-based:
files=(*); for x in {1..30}; do i=$((RANDOM % ${#files[@]})); echo "${files[i]}"; done
Note that neither version takes duplicates into account.