web-dev-qa-db-ja.com

ディレクトリからランダムなファイルを選択する最良の方法

Pythonのディレクトリからランダムファイルを選択する最良の方法は何ですか?

編集:これが私がやっていることです:

import os
import random
import dircache

dir = 'some/directory'
filename = random.choice(dircache.listdir(dir))
path = os.path.join(dir, filename)

これは特に悪いですか、それとも特に良い方法がありますか?

28
JasonSmith
import os, random
random.choice(os.listdir("C:\\")) #change dir name to whatever

編集した質問について:まず、dircacheを使用するリスクと、それが 2.6で非推奨、3.0で削除された であるという事実を知っていると思います。

第二に、競合状態がどこにあるのかわかりません。 dircacheオブジェクトは基本的に不変です(ディレクトリリストがキャッシュされた後、再度読み取られることはありません)。そのため、オブジェクトからの同時読み取りに害はありません。

それ以外に、このソリューションで問題が発生する理由がわかりません。それは結構です。

59
Yuval Adam

ディレクトリを含めたい場合は、Yuval Aが答えます。さもないと:

import os, random

random.choice([x for x in os.listdir("C:\\") if os.path.isfile(os.path.join("C:\\", x))])
6
mavnn

言語にとらわれないソリューション:

1)合計数を取得します。指定されたディレクトリ内のファイルの数。

2)0から[合計no。ファイル数-1]。

3)ファイル名のリストを適切にインデックス付けされたコレクションなどとして取得します。

4)n番目の要素を選択します。nは乱数です。

4
karim79

与えられたほとんどのソリューションの問題は、すべての入力をメモリにロードすることです。これは、大規模な入力/階層で問題になる可能性があります。これが、Tom ChristiansenとNat Torkingtonによる The Perl Cookbook を基にしたソリューションです。ディレクトリの下の任意の場所にランダムファイルを取得するには:

#! /usr/bin/env python
import os, random
n=0
random.seed();
for root, dirs, files in os.walk('/tmp/foo'):
  for name in files:
    n=n+1
    if random.uniform(0, n) < 1: rfile=os.path.join(root, name)
print rfile

少し一般化すると、便利なスクリプトになります。

$ cat /tmp/randy.py
#! /usr/bin/env python
import sys, random
random.seed()
n=1
for line in sys.stdin:
  if random.uniform(0, n)<1: rline=line
  n=n+1
sys.stdout.write(rline)

$ /tmp/randy.py < /usr/share/dict/words 
chrysochlore

$ find /tmp/foo -type f | /tmp/randy.py
/tmp/foo/bar
4
keithpjolley

最も簡単な解決策はos.listdirrandom.choiceメソッドを利用することです

random_file=random.choice(os.listdir("Folder_Destination"))

それを一歩一歩見てみましょう:-

1} os.listdirメソッドは、指定されたパスのエントリ(ファイル)の名前を含むリストを返します。

2}次に、このリストがパラメーターとしてrandom.choiceメソッドに渡され、リストからランダムなファイル名が返されます。

3}ファイル名はrandom_file変数に格納されます。


リアルタイムアプリケーションを検討

これはサンプルですpythonランダムなファイルをあるディレクトリから別のディレクトリに移動するコード

import os, random, shutil

#Prompting user to enter number of files to select randomly along with directory
source=input("Enter the Source Directory : ")
dest=input("Enter the Destination Directory : ")
no_of_files=int(input("Enter The Number of Files To Select : "))

print("%"*25+"{ Details Of Transfer }"+"%"*25)
print("\n\nList of Files Moved to %s :-"%(dest))

#Using for loop to randomly choose multiple files
for i in range(no_of_files):
    #Variable random_file stores the name of the random file chosen
    random_file=random.choice(os.listdir(source))
    print("%d} %s"%(i+1,random_file))
    source_file="%s\%s"%(source,random_file)
    dest_file=dest
    #"shutil.move" function moves file from one directory to another
    shutil.move(source_file,dest_file)

print("\n\n"+"$"*33+"[ Files Moved Successfully ]"+"$"*33)

Githubでプロジェクト全体をチェックアウトできますランダムファイルピッカー


os.listdirrandom.choiceメソッドに関する追加リファレンスについては、tutorialspoint learn pythonを参照してください。

os.listdir:- Python listdir()メソッド

random.choice:- Python choice()メソッド


1

使用する言語に依存せず、ディレクトリ内のファイルへのすべての参照を配列(「listFiles」など)のようなデータ構造に読み込み、配列の長さを取得できます。 「0」から「arrayLength-1」の範囲の乱数を計算し、特定のインデックスでファイルにアクセスします。これは、Pythonだけでなく機能するはずです。

1
Mork0075

事前にファイルが何であるかわからない場合は、リストを取得して、リストからランダムなインデックスを選択する必要があります。

これが1つの試みです。

_import os
import random

def getRandomFile(path):
  """
  Returns a random filename, chosen among the files of the given path.
  """
  files = os.listdir(path)
  index = random.randrange(0, len(files))
  return files[index]
_

[〜#〜] edit [〜#〜]:この質問では、「競合状態」の恐れについて言及していますが、私が推測できるのは、ランダムなファイルを選ぼうとする過程で。

I/O操作は本質的に「安全でない」、つまり失敗する可能性があることを念頭に置いておく以外に、それを回避する方法があるとは思いません。したがって、指定されたディレクトリでランダムに選択されたファイルを開くアルゴリズムは次のようになります。

  • 実際にはopen()は選択されたファイルであり、ファイルが存在しない可能性があるため、失敗を処理します
  • おそらく、それ自体を設定された試行回数に制限するので、ディレクトリが空の場合、またはファイルのどれも読み取り可能でない場合、それは死にません
1
unwind