Liệt kê X tệp ngẫu nhiên từ một thư mục


14

Có cách nào để liệt kê một tập hợp nói, 30 tệp ngẫu nhiên từ một thư mục sử dụng các lệnh Linux tiêu chuẩn không? (trong zsh)

Câu trả lời hàng đầu được mô tả ở đây không hoạt động đối với tôi ( sortkhông nhận ra tùy chọn -R)


Tôi tò mò bạn đang dùng hệ điều hành nào.
ixtmixilix

Câu trả lời:


7

Vì bạn đang đề cập đến zsh:

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

Bạn có thể thay thế printbằng nói ogg123*bằng nói**/*.ogg


19

Hãy thử đường ống lsđầu ra shuf, vd

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

Các -ncờ xác định có bao nhiêu tập tin ngẫu nhiên mà bạn muốn.


command not found(chưa cài đặt): /
Amelio Vazquez-Reina

Lạ thật ... nó nên là một phần của coreutils. Nếu coreutils của bạn đã cũ, thì lệnh sẽ không ở đó.
Renan

6
Đây là cách nhanh chóng và bẩn thỉu, và tôi cũng sẽ sử dụng nó - cho một kịch bản một lần. Đối với bất cứ điều gì bền hơn, tránh phân tích cú pháp đầu rals .
janmoesen

@janmoesen Tôi không biết về điều này. Cảm ơn!
Renan

@Renan Không phải mọi Unix đều có GNU coreutils được cài đặt theo mặc định.
Kusalananda

2

Thật dễ dàng để giải quyết điều này với một chút Perl. Chọn ngẫu nhiên bốn tệp từ thư mục hiện tại:

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

Mặc dù để sử dụng sản xuất, tôi sẽ sử dụng tập lệnh mở rộng không dựa vào lsđầu ra, có thể chấp nhận bất kỳ thư mục nào, kiểm tra đối số của bạn, v.v ... Lưu ý rằng bản thân lựa chọn ngẫu nhiên vẫn chỉ là một vài dòng.

#!/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 một tập lệnh Perl không phải là một 'lệnh unix tiêu chuẩn'. Vấn đề này rất dễ giải quyết trong bất kỳ ngôn ngữ kịch bản cấp cao nào như Perl, Python hoặc Ruby, nhưng thú vị hơn nếu nó trực tiếp trên dòng lệnh.
gerrit

1
@gerrit - Tôi lấy quan điểm của bạn. Tôi đã cung cấp điều này bởi vì câu trả lời ưa thích (sử dụng shuf) là không đủ cho OP. Đối với những gì là và không phải là tiêu chuẩn Unix - Perl tồn tại ở mọi nơi và nó giải quyết vấn đề ngắn gọn và mạnh mẽ. Nếu tôi đưa ra đây là một lớp lót Perl, liệu nó có được tính là 'dòng lệnh' không? Có phải thực tế Perl mạnh mẽ thực sự là một lập luận chống lại sự tồn tại của câu trả lời này?
ire_and_curses

Tôi muốn nói đó là một câu trả lời cho một câu hỏi khác. Tất nhiên, trong bất kỳ ngôn ngữ lập trình đầy đủ tính năng nào, vấn đề này là không đáng kể, đối với tôi, phần thú vị của câu hỏi là liệu nó có thể được thực hiện / không / sử dụng tập lệnh ~ 20 LỘC hay không; ngôn ngữ kịch bản rất mạnh, nhưng tôi không nghĩ Perl phân loại là một lệnh (chẳng hạn như OP đã yêu cầu; và không, nếu bạn đưa ra một dòng lệnh 200 ký tự gọi Perl tôi cũng có cùng quan điểm).
gerrit

@gerrit - Có lẽ tôi có thể rõ ràng hơn. Hãy xem bản chỉnh sửa của tôi: perl -MList::Util=shuffle -e 'print shuffle(ls )' | head -n 4Đây có giống với những gì bạn đang tìm kiếm không?
ire_and_curses

Vâng, tôi đã gỡ bỏ downvote của tôi mà phải thừa nhận là một chút khắc nghiệt.
gerrit

1

Một giải pháp đơn giản giúp tránh phân tích ls và cũng hoạt động với khoảng trắng:

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

Như đã thấy trong các bình luận khác, OP nằm trên một hệ thống không có shuf.
Kusalananda

Tránh shufkhông được đề cập trong câu hỏi. Câu trả lời này vẫn sẽ hữu ích cho những người dùng khác.
SCAI

0

Một oneliner không sử dụng gì ngoài Zsh:

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

Tương tự trong Bash, nơi các chỉ số mảng dựa trên zero:

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

Lưu ý rằng không có phiên bản nào có bản sao vào tài khoản.


1
Điều này có thể liệt kê cùng một tập tin nhiều lần. Tránh điều này là một phần quan trọng của vấn đề.
Gilles 'SO- ngừng trở nên xấu xa'

Gilles: hoàn toàn đúng, đó là lý do tại sao tôi nói "Lưu ý rằng không có phiên bản nào có bản sao vào tài khoản." Bạn vẫn có thể làm điều đó trong Bash thuần túy, nếu bạn không quan tâm đến độ phức tạp thời gian và xây dựng lại mảng mỗi khi bạn xóa một cái ngẫu nhiên khỏi nó. Thậm chí không gần với một lớp lót, nhưng tất nhiên đó không phải là một yêu cầu.
janmoesen
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.