Bir dizindeki X rastgele dosyayı listele


14

Standart Linux komutlarını kullanarak bir dizinden bir dizi 30 rasgele dosyayı listelemenin bir yolu var mı? (inç zsh)

Burada açıklanan üst yanıt benim için sortçalışmıyor ( seçeneği tanımıyor -R)


Hangi işletim sistemini kullandığınızı merak ediyorum.
ixtmixilix

Yanıtlar:


7

Zsh'den bahsettiğiniz için:

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

printSöyle ogg123ve *söyle ile değiştirebilirsiniz**/*.ogg


19

Boru dene lsçıktı shuf, örneğin

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

-nBayrak kaç istediğiniz rasgele dosyaları belirtir.


command not found(kurulu değil): /
Amelio Vazquez-Reina

Garip ... bu çekirdeklerin bir parçası olmalı. Coreutils'iniz eskiyse, komut orada olmayacaktır.
Renan

6
Bu hızlı ve kirli bir yoldur ve bunu da kullanırım - bir kerelik bir senaryo için. Daha dayanıklı bir şey için, çıktısını ayrıştırmaktan kaçınınls .
janmoesen

@janmoesen Bunu bilmiyordum. Teşekkürler!
Renan

@Renan Her Unix'te varsayılan olarak kurulu GNU coreutils yoktur.
Kusalananda

2

Bunu birazcık Perl ile çözmek oldukça kolaydır. Geçerli dizinden rastgele dört dosya seçin:

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

Üretim kullanımı için olsa da, lsçıktıya güvenmeyen, herhangi bir dizini kabul edebilen, argümanlarınızı kontrol edebilen, genişletilmiş bir komut dosyası ile giderdim . Rastgele seçimin kendisinin hala sadece birkaç satır olduğunu unutmayın.

#!/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";
}

Bir Perl betiği bir 'standart unix komutu' değildir. Bu sorunun Perl, Python veya Ruby gibi herhangi bir üst düzey komut dosyası dilinde çözülmesi kolaydır, ancak doğrudan komut satırındaysa daha ilginçtir.
gerrit

1
@gerrit - Demek istediğim. Bunu sağladım çünkü tercih edilen cevap (kullanma shuf) OP için yeterli değildi. Standart olan ve olmayan olana gelince, Unix - Perl her yerde var olur ve sorunu özlü ve sağlam bir şekilde çözer. Bunu Perl tek katlı olarak verirsem, bu 'komut satırı' olarak sayılır mı? Perl'in güçlü olması gerçekten bu cevabın varlığına karşı bir argüman mı?
ire_and_curses

Farklı bir sorunun cevabı olduğunu söyleyebilirim. Tabii ki tam özellikli herhangi bir programlama dilinde bu sorun önemsizdir, benim için sorunun ilginç kısmı ~ 20 LOC betiğine / olmadan / yapılabilirse; kodlama dilleri güçlüdür, ancak Perl'in bir komut olarak sınıflandırdığını sanmıyorum (OP'nin istediği gibi; hayır, Perl'i çağıran 200 karakterlik bir komut satırı vermiş olsaydınız aynı görüşe sahip olurdum).
gerrit

@gerrit - Belki daha net olabilirim. Benim düzenlememe bir göz atın: perl -MList::Util=shuffle -e 'print shuffle(ls )' | head -n 4Bu aradığınız gibi mi?
ire_and_curses

Evet, kuşkusuz biraz sert olan aşağı oyumu kaldırdım.
gerrit

1

Ls ayrıştırmasını önleyen ve boşluklarla çalışan basit bir çözüm :

shuf -en 30 dir/* | while read file; do
    echo $file
done

Diğer yorumlarda görüldüğü gibi, OP olmadan bir sistem üzerinde shuf.
Kusalananda

Kaçınılması shufsöz konusu değildir. Bu cevap diğer kullanıcılara da yardımcı olacaktır.
scai

0

Zsh dışında hiçbir şey kullanmayan bir oneliner:

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

Dizi indekslerinin sıfır tabanlı olduğu Bash için de aynı şey geçerlidir:

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

Her iki sürümün de kopyaları dikkate almadığını unutmayın.


1
Bu, aynı dosyayı bir kereden fazla listeleyebilir. Bundan kaçınmak sorunun önemli bir parçasıdır.
Gilles 'SO- kötü olmayı kes'

Gilles: Oldukça doğru, bu yüzden "Her iki versiyonun da kopyaları dikkate almadığını unutmayın." Dedim. Eğer zaman karmaşıklığını umursamıyorsanız ve rastgele bir tanesini her kaldırışınızda diziyi yeniden oluşturursanız, yine de saf Bash'ta yapabilirsiniz. O zaman tek bir astara bile yakın değil, ama elbette bu bir gereklilik değildi.
janmoesen
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.