シェルで大量のファイルを管理する方法は?


9

$ ls ./dir_with_huge_amount_of_files/errors/

ディレクトリがUNIXタイムスタンプのある画像でいっぱいだとすると、多くの場合、多くのGBまたはそれ以上で測定されます。のようなシェルコマンドlsは、数百万(またはそれ以上)の画像で動作するように設計されていないため、オーバーフロースタイルの警告が表示されます。このような大量のファイルをどのように管理できますか?たとえば、(名前と作成時刻のタイムスタンプに基づいて)真ん中の画像を検索したい場合、組み込みの検索機能を提供するファイルシステムはありますか?どのコマンドを使用しますか?私は快適にしようとしたlsし、find必要なフラグ付きですが、それらは非常に遅いか生成された警告のいずれかでした。基本的に、写真のiノードを時系列に配置するための配列が1つ必要です。どうやってするか?その後、unixタイムスタンプを含むメタデータを追加できます。

[更新]

現在の回答には深刻な欠陥があり、人々は経験的なテストなしに、ある種の回答を投稿するだけです。彼らが提案をテストした場合、おそらく失敗するでしょう。したがって、サンドボックスを作成して膨大な量のファイルを作成し、1e7の量のファイルのように提案をテストできるコマンドラインツールを作成しました。ファイルの生成には時間がかかることがありますので、しばらくお待ちください。誰かがこれを行うためのより速い方法を知っている場合は、コードを編集してください。入力python code.py --helpしてヘルプを表示します。楽しんで!

多くのdirredファイルを作成するための使用例

$ ls ./data2
ls: ./data2: No such file or directory
$ python testFill.py -n 3 -d 7                                                 
$ tree data2/                                                                  
data2/
|-- 0
|   |-- 1302407302636973
|   |-- 1302407302638022
|   `-- 1302407302638829
|-- 1
|   |-- 1302407302639604
|   |-- 1302407302641652
|   `-- 1302407302642399
|-- 2
|   |-- 1302407302643158
|   |-- 1302407302645223
|   `-- 1302407302646026
|-- 3
|   |-- 1302407302646837
|   |-- 1302407302649110
|   `-- 1302407302649944
|-- 4
|   |-- 1302407302650771
|   |-- 1302407302652921
|   `-- 1302407302653685
|-- 5
|   |-- 1302407302654423
|   |-- 1302407302656352
|   `-- 1302407302656992
`-- 6
    |-- 1302407302657652
    |-- 1302407302659543
    `-- 1302407302660156

7 directories, 21 files

コードtestFill.py

# Author: hhh
# License: ISC license

import os, math, time, optparse, sys

def createHugeAmountOfFiles(fileAmount, dirAmount):
   counter = 0
   DENSITY = 1e7
   dir = "./data/"

   do = dir+str(counter)+"/"
   while (os.path.exists(do)):
      counter = counter+1
      do = dir+str(counter)+"/"

   os.mkdir(do)

   for d in range(int(dirAmount)):
      for f in range(int(fileAmount)):
         timeIt = int(time.time()*1e6)
         if (not os.path.exists(do)):
            os.mkdir(do)

         if (timeIt % DENSITY == 0):
            counter = counter+1
            do = dir+str(counter)+"/"

            if (not os.path.exists(do)):
               os.mkdir(do)


         do = dir+str(counter)+"/"
         if(not os.path.exists(do)):
            os.mkdir(do)

         f = open(do+str(timeIt), 'w')
         f.write("Automatically created file to test Huge amount of files.")
         f.close()
      counter = counter +1


def ls(dir):
   for root, dirs, files in os.walk("./data/"+dir):
      print(files)

def rm(dir):
   for root, dirs, files in os.walk("./data/"+dir):
      for f in files:
         os.remove("./data/"+dir+"/"+f)


def parseCli():
   parser = optparse.OptionParser()
   parser.add_option("-f", "--file", dest="filename",
                     help="Location to remove files only in ./Data.", metavar="FILE")
   parser.add_option("-n", "--number", dest="number",
                     help="Number of files to generate", metavar="NUMBER")
   parser.add_option("-r", "--remove", dest="remove",
                     help="Data -dir content to remove", metavar="NUMBER")
   parser.add_option("-d", "--dir", dest="dir",
                     help="Amount of dirs to generate", metavar="NUMBER")
   parser.add_option("-q", "--quiet",
                     action="store_false", dest="verbose", default=True,
                     help="don't print status messages to stdout")

   return parser.parse_args()

def main():
   (options, args) = parseCli()

   if (options.filename):
      ls(options.filename)
   if (options.number and options.dir):
      createHugeAmountOfFiles(options.number, options.dir)
   if (options.remove):
      rm(options.remove)


main()

2
@hhhこの規模でのデータセットのために適切にインデックス-ED DBは、おそらく唯一のオプションです
xenoterracide

@xenoterracide:しかし、dbsでも配列のようなものを使用した高速検索を実装する必要がある場合、dbはやり過ぎに聞こえます。写真撮影のソースはこちら:github.com/fsphil/fswebcam。おそらく、画像を保存する時間を少し変更して、ファイルにinode-number&unix-time-stampの行を追加することができます。今では写真ではなく線で、写真を検索する方がはるかに速くなります。あるいはもっと簡単に、画像がディスクに保存されるたびに、そのタイムスタンプのファイルに行を追加します。ラウンドアラウンドソリューション。しかし、現在の写真の問題は解決しないので、関連する質問をしてください。

@hhhどのファイルシステムを使用していますか?または、それはまだ問題ではありません... extには、デフォルトではオンになっていない可能性があるいくつかのパフォーマンス強化機能があります。それでもおそらくあなたが話している規模では対処しないでしょう。DBはこれらに最適化されており、それらを処理するためのさまざまなインデックス作成ソリューションを備えています。たとえば、btreeインデックスは単なる配列ではありません...
xenoterracide

@xenoterracide:ext3、それが重要かどうかも不明。私が示した解決策は、将来の検索問題の問題を解決すると思いますが、現在の写真ではまったく役に立たず、検索に非常に時間がかかります。

1
1つのディレクトリに数百万のファイルがありますか?その場合は、ファイル名の最初の文字に基づいて、1レベルまたは2レベルの深いサブディレクトリでそれらを分割することを検討してください。例:a/b/abcdef.jpg
alex

回答:


4

別のシェルを試してください。たとえばzshを試すことをお勧めします。これにより、より多くのパラメーターが許可されるかどうかを確認します。

私が正しく理解していれば、ファイル名の一部はUNIXタイムスタンプです。ファイルをフォルダーに分割することをお勧めします。日付/時刻形式がUNIXエポック番号である場合は、その番号の分数のチャンク(たとえば10000)を別のフォルダーに入れます。

ISO 8601タイムスタンプがファイル名の一部である場合は、単に年、月、または日で除算します。


1
lsとfindはbashとzshのどちらにも組み込まれていないため、このインスタンスでシェルの切り替えがどのように役立つかは不明です。
ロビングリーン

シェル拡張についてです。シェルがグロビングを展開できない場合は、これが問題である可能性があります。
ポールモン2011年

約1e6ファイルでコマンドを実行するテストをいくつか行いましたが、ZSHは同じ問題に直面しています"$ cp * Test/ ksh: cp: Argument list too long % rm * zsh: sure you want to delete all the files in /home/user/Downloads [yn]? y zsh: argument list too long: rm % ls * zsh: argument list too long: ls "。申し訳ありませんが、これが質問-1にどのように関連しているかはわかりません。これは、これをテストし、1e6ファイルを作成してコマンドを実行するのが非常に簡単だったためです。

1

でしょうlocate(もちろんupdatedb)あなたにどんな助けになりますか?


1
updatedb使用しfindます。
dave1010 2011年

@ dave1010、確かに、バックグラウンドでたまにそうするので、OPが毎分最新でなくてもかまいませんが、おそらく1日に1回であれば、静かな時間にupdatebをスケジュールします(または頻繁にupdatebをスケジュールしますが、優先度は低く(これは本来あるべきものです)、locateを使用すると、必要なものをすばやく見つけることができます。したがって、重要な問題は、DB(または他のそのようなシステムのインデックス)をどのように最新にする必要があるかです。
asoundmove
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.