รายการ X ไฟล์สุ่มจากไดเรกทอรี


14

มีวิธีในการแสดงรายการชุดของไฟล์ที่สุ่ม 30 ไฟล์จากไดเรกทอรีโดยใช้คำสั่ง Linux มาตรฐานหรือไม่? (ในzsh)

คำตอบสูงสุดที่อธิบายไว้ที่นี่ไม่ทำงานสำหรับฉัน ( sortไม่รู้จักตัวเลือก-R)


ฉันอยากรู้ว่าคุณใช้ระบบปฏิบัติการอะไรอยู่
ixtmixilix

คำตอบ:


7

เนื่องจากคุณกำลังพูดถึง zsh:

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

คุณสามารถแทนที่printด้วยคำพูดogg123และ*ด้วยคำพูด**/*.ogg


19

ลองใช้ท่อlsส่งออกไปshufเช่น

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

การ-nตั้งค่าสถานะระบุจำนวนไฟล์สุ่มที่คุณต้องการ


command not found(ไม่ได้ติดตั้ง): /
Amelio Vazquez-Reina

แปลก ... มันควรเป็นส่วนหนึ่งของ coreutils หาก coreutils ของคุณเก่าแล้วคำสั่งจะไม่อยู่ที่นั่น
Renan

6
นี่เป็นวิธีที่รวดเร็วและสกปรกและฉันก็จะใช้มันเช่นกันสำหรับสคริปต์แบบใช้ครั้งเดียว สำหรับสิ่งที่คงทนมากขึ้นหลีกเลี่ยงการแยกวิเคราะห์การส่งออกของ ls
janmoesen

@janmoesen ฉันไม่รู้เกี่ยวกับเรื่องนี้ ขอบคุณ!
Renan

@ Renan ไม่ทุก Unix มี GNU coreutils ติดตั้งโดยค่าเริ่มต้น
Kusalananda

2

มันค่อนข้างง่ายที่จะแก้ปัญหานี้ด้วย Perl เล็กน้อย เลือกสี่ไฟล์โดยการสุ่มจากไดเรกทอรีปัจจุบัน:

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

สำหรับการใช้งานจริงฉันจะไปกับสคริปต์ที่ไม่ต้องพึ่งพาlsเอาท์พุทสามารถรับ dir ใด ๆ ตรวจสอบ args ของคุณเป็นต้นโปรดทราบว่าการเลือกแบบสุ่มนั้นยังคงเป็นเพียงสองบรรทัด

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

Imho Perl-script ไม่ใช่ 'คำสั่ง unix มาตรฐาน' ปัญหานี้แก้ไขได้ง่ายในภาษาสคริปต์ระดับสูงเช่น Perl, Python หรือ Ruby แต่น่าสนใจกว่าถ้ามันอยู่บน commandline โดยตรง
gerrit

1
@gerrit - ฉันเอาประเด็นของคุณ ฉันให้สิ่งนี้เพราะคำตอบที่ต้องการ (ใช้shuf) ไม่เพียงพอสำหรับ OP สำหรับสิ่งที่เป็นและไม่ใช่มาตรฐาน Unix - Perl นั้นมีอยู่ทุกหนทุกแห่งและจะแก้ปัญหาได้อย่างกระชับและแข็งแรง ถ้าฉันได้รับสิ่งนี้เป็น Perl One-Liner, นั่นจะนับเป็น 'command line' หรือไม่? ความจริงแล้ว Perl มีประสิทธิภาพจริงๆแล้วมันขัดแย้งกับการมีอยู่ของคำตอบนี้หรือไม่?
ire_and_curses

ฉันว่ามันเป็นคำตอบสำหรับคำถามอื่น แน่นอนในการเขียนโปรแกรมภาษาเต็มรูปแบบปัญหานี้เป็นเรื่องเล็กน้อยสำหรับฉันส่วนที่น่าสนใจของคำถามคือถ้ามันสามารถทำได้ / ไม่ / / หันไปใช้สคริปต์ ~ 20 LOC; ภาษาสคริปต์มีประสิทธิภาพ แต่ฉันไม่คิดว่า Perl จัดหมวดหมู่เป็นคำสั่ง (เช่น OP ขอให้; และไม่ถ้าคุณให้ commandline 200 ตัวอักษรที่เรียกว่า Perl ฉันมีความเห็นเดียวกัน)
gerrit

@gerrit - บางทีฉันอาจชัดเจนกว่านี้ ลองดูที่การแก้ไขของฉัน: perl -MList::Util=shuffle -e 'print shuffle(ls )' | head -n 4นี่เป็นสิ่งที่คุณกำลังมองหาใช่ไหม?
ire_and_curses

ใช่ฉันลบ downvote ซึ่งยอมรับว่าค่อนข้างรุนแรง
gerrit

1

ทางออกที่ง่ายที่หลีกเลี่ยงการแยกวิเคราะห์ lsและยังใช้งานได้กับช่องว่าง:

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

เท่าที่เห็นในความคิดเห็นอื่น ๆ , OP shufอยู่ในระบบได้โดยไม่ต้อง
Kusalananda

การหลีกเลี่ยงshufไม่ได้กล่าวถึงในคำถาม คำตอบนี้จะยังคงเป็นประโยชน์กับผู้ใช้รายอื่น
scai

0

Oneliner ไม่มีอะไรนอกจาก Zsh:

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

เช่นเดียวกับใน Bash โดยที่ดัชนีอาเรย์นั้นเป็นศูนย์

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

โปรดทราบว่าไม่มีรุ่นใดที่จะนำมาพิจารณาซ้ำ


1
นี่อาจแสดงรายการไฟล์เดียวกันมากกว่าหนึ่งครั้ง การหลีกเลี่ยงปัญหานี้เป็นส่วนสำคัญของปัญหา
Gilles 'หยุดความชั่วร้าย'

Gilles: ถูกต้องซึ่งเป็นเหตุผลที่ฉันพูดว่า "โปรดทราบว่าไม่มีรุ่นใดที่จะนำมาพิจารณาซ้ำกัน" คุณยังสามารถทำได้ใน Bash บริสุทธิ์หากคุณไม่สนใจเกี่ยวกับความซับซ้อนของเวลาและสร้างอาร์เรย์ขึ้นใหม่ทุกครั้งที่คุณลบสุ่มออกจากมัน ไม่แม้แต่ใกล้กับสายการบินเดียว แต่แน่นอนว่าไม่ใช่ข้อกำหนด
janmoesen
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.