디렉토리에서 X 랜덤 파일 나열


14

표준 Linux 명령을 사용하여 디렉토리에서 30 개의 임의 파일 세트를 나열하는 방법이 있습니까? (에서 zsh)

여기에 설명 된 최고의 답변 이 저에게 효과적 sort이지 않습니다 ( 옵션을 인식하지 못합니다 -R)


나는 당신이 어떤 OS를 사용하고 있는지 궁금합니다.
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 모든 유닉스에 기본적으로 GNU coreutils가 설치되어있는 것은 아닙니다.
Kusalananda

2

작은 Perl로 이것을 해결하는 것은 매우 쉽습니다. 현재 디렉토리에서 무작위로 4 개의 파일을 선택하십시오.

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

그러나 프로덕션 용도로는 ls출력에 의존하지 않고 확장 된 스크립트를 사용하여 디렉토리를 수락하고 인수를 검사하는 등의 작업을 수행합니다. 무작위 선택 자체는 여전히 두 줄에 불과합니다.

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

Perl 스크립트 Imho는 '표준 유닉스 명령'이 아닙니다. 이 문제는 Perl, Python 또는 Ruby와 같은 고급 스크립팅 언어에서 쉽게 해결할 수 있지만 명령 줄에 직접있는 경우 더 흥미 롭습니다.
gerrit

1
@gerrit-당신의 요점을 이해합니다. 선호 답변 (을 사용하여 shuf)이 OP에 충분하지 않기 때문에 이것을 제공했습니다 . 표준 유닉스가 무엇인지 아닌지에 관해서-Perl은 어디에나 존재하며 간결하고 강력하게 문제를 해결합니다. 이것을 Perl one-liner로 지정했다면 'command line'으로 계산 되었습니까? Perl이 강력하다는 사실이 실제로이 답변의 존재에 대한 논쟁입니까?
ire_and_curses

나는 그것이 다른 질문에 대한 대답이라고 말하고 싶습니다. 물론 모든 기능을 갖춘 프로그래밍 언어에서이 문제는 사소한 문제입니다. 저에게 흥미로운 부분은 ~ 20 LOC 스크립트를 사용하거나 수행하지 않고 수행 할 수 있는지 여부입니다. 스크립팅 언어는 강력하지만 Perl을 명령으로 분류하지는 않는다고 생각합니다 (예 : OP가 요청한 것과 같지 않습니다)
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

Zsh 이외의 것을 사용하는 oneliner :

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

배열 인덱스가 0부터 시작하는 Bash와 동일합니다.

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

두 버전 모두 중복을 고려하지 않습니다.


1
동일한 파일이 두 번 이상 나열 될 수 있습니다. 이것을 피하는 것은 문제의 중요한 부분입니다.
질 'SO-정지 존재 악마'

Gilles : 아주 그렇기 때문에 "두 버전 모두 중복을 고려하지 않습니다." 시간 복잡성에 신경 쓰지 않고 배열에서 임의 배열을 제거 할 때마다 배열을 다시 작성하면 순수한 Bash에서 여전히 할 수 있습니다. 원 라이너에 가깝지는 않지만 물론 요구 사항은 아닙니다.
janmoesen
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.