Kabuktaki çok sayıda dosya nasıl yönetilir?


9

$ ls ./dir_with_huge_amount_of_files/errors/

Bir dizinin unix zaman damgalarına sahip resimlerle dolu olduğunu varsayalım, birçok GB veya daha fazlasında ölçülen çok şey var. Gibi kabuk komutları ls, milyonlarca (veya daha fazla) resim ile çalışmak üzere tasarlanmadığından taşma tarzı uyarılar alır. Bu kadar büyük miktarda dosyayı nasıl yönetebilirim? Örneğin, resmi ortada bulmak istiyorsam (ad ve oluşturma süresindeki zaman damgasına göre), yerleşik bir arama özelliği sunan bazı dosya sistemi var mı? Hangi komutları kullanırsınız? Konforu denedim lsvefindgerekli bayrakları ile ama ya çok yavaş ya da uyarılar üretti bu yüzden ya daha iyi bir dosya sistemi ya da db ya da resimleri önceden indekslemek için böyle bir şeye ihtiyacım olduğunu düşünüyorum. Temelde fotoğrafların inode kronolojik sırada yerleştirilmesi gereken bir dizi gerekir. Bu nasıl yapılır? Daha sonra, unix-zaman damgaları içeren meta veriler eklenebilir.

[Güncelleme]

Şu anki cevaplarda ciddi bir kusur var, insanlar ampirik testler olmadan sadece cevaplar gönderiyorlar. Eğer önerilerini test etselerdi, muhtemelen başarısız olurlardı. Bu nedenle, size büyük miktarda dosya oluşturmak ve önerilerinizi 1e7 miktarda dosya gibi test etmek için sanal alan oluşturabileceğiniz bir komut satırı aracı oluşturdum. Dosyaları oluşturmak uzun sürebilir, bu yüzden sabırlı olun. Birisi bunu yapmanın daha hızlı bir yolunu biliyorsa, lütfen kodu düzenleyin. Tip python code.py --helpYardım almak için. İyi eğlenceler!

Çok sayıda dirred dosya oluşturmak için Kullanım Örneği

$ 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

Kod testiFill.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 dataset'in bu ölçekte uygun şekilde indekslenmiş bir db muhtemelen tek seçenektir
xenoterracide 25:11

@xenoterracide: ancak dbs bile diziler gibi bir şeyle hızlı arama yapmalıdır, db aşırıya kaçar. Fotoğraf çekmenin kaynağı burada: github.com/fsphil/fswebcam . Belki, resmi kaydettiği zaman biraz değiştirebilirim, böylece dosyaya inode-numarası ve unix-zaman damgası olan bir satır ekleyebilirim. Şimdi resimlerle değil, çizgilerle, resimleri aramak çok daha hızlı olurdu. Ya da daha kolay, bir resim bir diske her kaydedildiğinde, zaman damgasının bir dosyasına bir satır eklerim. Yuvarlak çözüm. Ancak mevcut resimlerle sorunu çözmeyecek, bu yüzden soru ile ilgili.

@hhh hangi dosya sistemini kullanıyorsunuz? ya da henüz önemli değil ... ext, varsayılan olarak açık olmayan bazı performans artırıcı özelliklere sahiptir. Her ne kadar bunlar muhtemelen konuştuğunuz ölçekte ilgilenmeyecektir. DB'ler bu şeyler için optimize edilmiştir ve bunlarla başa çıkmak için çeşitli indeksleme çözümlerine sahiptir. örneğin bir btree endeksi sadece basit bir dizi değildir ...
xenoterracide 25:01

@xenoterracide: ext3, önemli olup olmadığından emin değilim. Gösterdiğim çözümün gelecekteki arama sorunu için sorunu çözdüğünü düşünüyorum, ancak mevcut fotoğraflarla hiç yardımcı olmuyor, aramak çok zaman alıyor.

1
Tek bir dizinde milyonlarca dosyanız var mı? Eğer öyleyse, onları dosya adının ilk karakterlerine göre bir veya iki seviyeli derin alt dizinlere bölmeyi düşünebilirsiniz, örneğin:a/b/abcdef.jpg
alex

Yanıtlar:


4

Farklı bir kabuk deneyin. Örneğin zsh denemenizi tavsiye ederim ve daha fazla parametreye izin verip vermediğine bakın.

Dosya adının bir parçası olarak doğru anlarsam UNIX zaman damgası olur. Dosyaların klasörlere bölünmesi tavsiye edilebilir. Tarih / saat biçimi bir UNIX çağırma numarasıysa, bu sayının kesir parçalarını (örneğin 10000'ler) ayrı bir klasöre koyun.

Bir Eğer ISO 8601 damgası dosya adının bir parçası, sadece yıl, ay veya gün geçtikçe bölün.


1
ls ve find, bash veya zsh içinde yerleşik değildir, bu nedenle kabukların bu durumda nasıl yardımcı olacağı belirsizdir.
Robin Green

Kabuk genişlemesi ile ilgili. Kabuk globbing'i genişletemezse, sorun bu olabilir.
Polemon

Ben birkaç testler 1E6 hakkında dosyalar üzerinde komutları çalıştırarak, ZSH aynı sorunlarla karşı karşıyadır yaptı: "$ 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 ". Maalesef bunun -1 sorusuyla nasıl ilişkili olduğunu göremiyorum çünkü bunu test etmek, sadece 1e6 dosyaları oluşturmak ve komutları çalıştırmak çok kolaydı.

1

Misiniz locate(ve tabii ki updatedb) size herhangi bir yardımım?


1
updatedbkullanır find.
dave1010

@ dave1010, elbette, ancak bunu arka planda bir kez yapar, bu nedenle OP'nin her dakika güncel olması gerekmiyorsa, ancak belki günde bir kez, daha sonra sessiz bir saatte (veya sık sık ama yine de olması gereken budur düşük öncelikli olarak zamanlanmış zamanlama), sonra locate kullanmak istediğinizi bulmak çok hızlı. Bu yüzden anahtar soru, DB'nin (veya bu tür herhangi bir sistemin dizininin) ne kadar güncel olması gerektiğidir.
asoundmove
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.