Bagaimana cara mengelola sejumlah besar file di shell?

9

$ ls ./dir_with_huge_amount_of_files/errors/

Misalkan direktori penuh dengan gambar dengan cap waktu unix, maksud saya banyak diukur dalam banyak GB atau bahkan lebih. Perintah Shell seperti lsakan mendapatkan peringatan gaya meluap karena mereka tidak dirancang untuk bekerja dengan jutaan (atau lebih) gambar. Bagaimana saya bisa mengatur jumlah file yang begitu besar? Jika, misalnya, saya ingin menemukan gambar di tengah (sesuai stempel waktu dalam nama dan waktu pembuatan), apakah ada beberapa sistem file yang menawarkan fitur pencarian bawaan? Perintah mana yang akan Anda gunakan? Saya mencoba yang nyaman lsdanfinddengan flag yang diperlukan tetapi peringatannya lambat atau menghasilkan peringatan jadi saya berpikir bahwa saya perlu sistem file atau db yang lebih baik atau sesuatu seperti itu untuk mengindeks gambar. Saya pada dasarnya memerlukan satu larik yang inode foto harus ditempatkan dalam urutan kronologis. Bagaimana cara melakukannya? Kemudian, metadata dengan cap waktu unix dapat ditambahkan.

[Memperbarui]

Ada kesalahan serius dalam jawaban saat ini, orang hanya memposting semacam-jawaban tanpa tes empiris. Jika mereka menguji saran mereka, mereka mungkin akan gagal. Oleh karena itu, saya membuat Anda alat baris perintah di mana Anda dapat membuat kotak pasir untuk membuat sejumlah besar file dan menguji saran Anda seperti dengan jumlah file 1e7. Butuh waktu lama untuk menghasilkan file jadi bersabarlah. Jika seseorang tahu cara yang lebih cepat untuk melakukan ini, harap edit kode. Ketik python code.py --helpuntuk mendapatkan bantuan. Selamat bersenang-senang!

Contoh Penggunaan untuk membuat banyak file yang 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

Kode 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()
Kevin Bowen
sumber
2
@hhh untuk dataset pada skala ini, db indeks-ed yang benar mungkin satu-satunya pilihan
xenoterracide
@ xenoterracide: tetapi bahkan dbs harus menerapkan pencarian cepat dengan sesuatu seperti array, db terdengar berlebihan. Sumber untuk pengambilan gambar ada di sini: github.com/fsphil/fswebcam . Mungkin, saya bisa sedikit mod waktu menyimpan gambar sehingga saya bisa menambahkan baris dengan nomor inode & unix-time-cap ke file. Sekarang bukan dengan gambar tetapi garis, akan jauh lebih cepat untuk mencari gambar. Atau bahkan lebih mudah, setiap kali gambar disimpan ke disk, saya menambahkan baris ke file cap waktu. Solusi menyeluruh. Tetapi tidak akan menyelesaikan masalah dengan gambar saat ini jadi pertanyaan yang relevan.
@ hhh filesystem apa yang Anda gunakan? atau belum penting ... ext memang memiliki beberapa fitur peningkatan kinerja yang mungkin tidak diaktifkan secara default. Meskipun mereka mungkin tidak akan berurusan dengan skala yang Anda bicarakan. DB dioptimalkan untuk hal-hal ini dan memiliki berbagai solusi pengindeksan untuk menghadapinya. misalnya indeks btree bukan hanya array sederhana ...
xenoterracide
@ xenoterracide: ext3, tidak yakin apakah itu penting. Saya pikir solusi yang saya ilustrasikan memperbaiki masalah untuk masalah pencarian di masa depan tetapi itu tidak membantu sama sekali dengan foto saat ini, sangat memakan waktu untuk mencarinya.
1
Apakah Anda memiliki jutaan file dalam satu direktori? Jika demikian, Anda dapat mempertimbangkan membaginya dengan satu atau dua tingkat subdir, berdasarkan karakter pertama dari nama file, misalnya:a/b/abcdef.jpg
alex

Jawaban:

4

Coba shell yang berbeda. Saya akan merekomendasikan mencoba zsh misalnya, dan lihat apakah itu memungkinkan lebih banyak parameter.

Jika saya mengerti dengan benar, bagian dari nama file, adalah cap waktu UNIX. Mungkin disarankan, untuk membagi file ke dalam folder. Jika format tanggal / waktu adalah nomor zaman UNIX, masukkan bilangan pecahan dari angka itu, misalnya 10.000, dalam folder terpisah.

Jika stempel waktu ISO 8601 adalah bagian dari nama file, cukup bagi dengan tahun, bulan atau hari.

polemon
sumber
1
ls dan find bukan bawaan di bash atau zsh, jadi tidak jelas bagaimana menukar shell akan membantu dalam hal ini.
Robin Green
Ini tentang ekspansi shell. Jika shell tidak dapat memperluas globbing, ini mungkin masalahnya.
polemon
Saya membuat beberapa tes menjalankan perintah di sekitar 1E6 file, zsh menghadapi masalah yang sama: "$ 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 ". Maaf tapi saya tidak bisa melihat bagaimana ini terkait dengan pertanyaan -1 karena sangat mudah untuk menguji ini, buat hanya file 1e6 dan jalankan perintah.
1

Apakah locate(dan tentu saja updatedb) dapat membantu Anda?

pindahkan
sumber
1
updatedbmenggunakan find.
dave1010
@ dave1010, tentu saja, tetapi kadang-kadang melakukannya di latar belakang, jadi jika dapat diterima OP untuk tidak perlu memperbarui setiap menit, tapi mungkin sekali sehari, maka jadwalkan updateb pada jam yang tenang (atau jadwalkan updatedb sering tetapi dengan prioritas rendah, yang seharusnya), kemudian menggunakan loc sangat cepat untuk menemukan apa yang Anda inginkan. Jadi pertanyaan kuncinya adalah seberapa mutakhir apakah DB (atau indeks untuk sistem lainnya) perlu.
asoundmove