ディレクトリからX個のランダムファイルを一覧表示する


14

標準のLinuxコマンドを使用して、ディレクトリから30個のランダムなファイルのセットをリストする方法はありますか?(にzsh

ここで説明さている一番上の答えは私にsortはうまくいきません(オプションを認識しません-R


どのOSを使用しているのか興味があります。
ixtmixilix

回答:



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(インストールされていない):/
アメリオバスケスレイナ

奇妙な...それはcoreutilsの一部でなければなりません。coreutilsが古い場合、コマンドはそこにありません。
レナン

6
これは迅速で汚い方法であり、私もそれを使用します—一回限りのスクリプトのために。より耐久性のあるものについては、の出力を解析しないでくださいls
ジャンモーセン

@janmoesen私はこれについて知りませんでした。ありがとう!
レナン

@RenanすべてのUnixにデフォルトでGNU coreutilsがインストールされているわけではありません。
クサラナナンダ

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スクリプトは「標準のUNIXコマンド」ではありません。この問題は、Perl、Python、Rubyなどの高レベルのスクリプト言語では簡単に解決できますが、コマンドラインに直接ある場合はさらに興味深いものになります。
-gerrit

1
@gerrit-私はあなたの主張を受け入れます。優先回答(を使用shuf)がOPにとって十分ではなかったため、これを提供しました。標準のUnixとそうでないものについては、Perlはどこにでも存在し、問題を簡潔かつ堅牢に解決します。これをPerlのワンライナーとして指定した場合、それは「コマンドライン」としてカウントされますか?Perlが強力であるという事実は、本当にこの答えの存在に対する議論なのでしょうか?
ire_and_curses

別の質問への答えだと思います。もちろん、すべての機能を備えたプログラミング言語では、この問題は些細なことです。私にとって興味深いのは、〜20 LOCスクリプトを使用せずに/なしで実行できるかどうかです。スクリプト言語は強力ですが、Perlがコマンドとして分類されるとは思いません(OPが要求していたなど。そして、Perlを呼び出す200文字のコマンドラインを与えた場合、私は同じ意見を持っていたでしょう)。
gerrit

@gerrit-おそらくもっと明確にできるでしょう。私の編集を見てください:perl -MList::Util=shuffle -e 'print shuffle(ls )' | head -n 4これはあなたが探していたものに似ていますか?
ire_and_curses

ええ、私は確かに少し過酷な私の投票を削除しました。
gerrit

1

lsの解析回避し、スペースでも機能するシンプルなソリューション:

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

他のコメントで見られるように、OPはなしのシステム上にありますshuf
クサラナナンダ

shuf質問では、回避については言及していません。この回答は、他のユーザーにとっても役立ちます。
scai

0

Zshのみを使用するoneliner:

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
これにより、同じファイルが複数回リストされる場合があります。これを回避することは問題の重要な部分です。
ジル「SO-悪であるのをやめる」

Gilles:まったくその通りです。だから「どちらのバージョンも重複を考慮に入れていないことに注意してください」と言ったのです。時間の複雑さを気にせず、ランダムな配列を削除するたびに配列を再構築する場合、純粋なBashでそれを行うことができます。ワンライナーに近いというわけではありませんが、もちろんそれは要件ではありませんでした。
ジャンモエセン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.