Mengapa memindahkan beberapa file dalam folder lebih lama daripada memindahkan seluruh folder?

21

Saya memiliki jutaan gambar di server cloud ubuntu saya. Ketika saya memindahkan folder lengkap yang berisi 12 juta gambar menggunakan mvperintah, itu terjadi hampir secara instan. Namun, ketika saya mvhanya gambar (bukan folder) maka dibutuhkan waktu. Apakah ada cara untuk memindahkan semua gambar secepat folder?

Inilah yang terjadi:

  1. folder src memiliki 12 juta gambar dan saya memindahkan ini ke folder dst menggunakan

    $ mv  src ../dst
    

    Terjadi segera

  2. Di dalam folder src saya melakukan ini untuk memindahkan:

    find -maxdepth 1 -name '*.jpg' -exec mv -t ../../dst/ {} +
    

    Ini membutuhkan waktu.

Apakah ada cara untuk mempercepat proses kedua?

sankit
sumber
1
Bukan solusi - tetapi untuk mengklarifikasi: cmd2 harus lebih lambat kemudian cmd1 karena menggunakan find dan kemudian jalankan langkah untuk hasilnya. Ini tidak akan pernah secepat gerakan langsung tanpa proses pra-temukan.
dufte
mungkin dstada di partisi sedangkan ../../dstyang lain.
phuclv
Seperti yang ditulis ini bahkan tidak terlihat seperti permohonan mencari yang valid. Tidak ada {}argumen di mana nama file akan diperluas.
R ..
Saya telah mengirimkan suntingan yang mengubah judul, menghapus referensi ke "gambar" dan menggantinya dengan inti masalah - itu memindahkan file individu vs memindahkan seluruh folder. Saya harap itu diterima oleh seseorang dengan perwakilan untuk melakukannya.
Monty Harder
1
Ini bukan permohonan yang valid dari find. find ... -exec mv -t ../../dst/ {} \;akan memanggil mvsekali per file; find ... -exec mv -t ../../dest {} +akan jauh lebih cepat, menyalin sebanyak mungkin file per panggilan, tetapi masih tidak secepat memindahkan direktori itu sendiri seperti dijelaskan oleh dadexix86 .
chepner

Jawaban:

50

TL; DR : Tidak

Untuk jumlah file yang lebih kecil, Anda tidak perlu findtetapi, bahkan dalam kasus yang disederhanakan dan lebih kecil ini, jika Anda mau

mv *.jpg ../../dst/

ini akan membutuhkan lebih banyak waktu daripada memindahkan seluruh direktori sekaligus.


Mengapa? Intinya adalah memahami apa yang mvdilakukan.

Secara singkat, mvmemindahkan angka (yang mengidentifikasi direktori, atau file) dari inode (direktori yang mengandungnya) ke yang lain, dan indeks ini diperbarui dalam jurnal sistem file atau FAT (jika sistem file diimplementasikan sedemikian rupa).

Jika sumber dan tujuan berada pada sistem file yang sama, tidak ada pergerakan data yang sebenarnya, itu hanya mengubah posisi, titik di mana mereka dilampirkan.

Jadi, ketika Anda mv satu direktori, Anda melakukan operasi ini satu kali .

Tetapi ketika Anda memindahkan 1 juta file, Anda melakukan operasi ini 1 juta kali .

Untuk memberi Anda contoh praktis, Anda memiliki pohon dengan banyak cabang. Secara khusus, ada satu simpul di mana 1 juta cabang dilampirkan.
Untuk memotong cabang-cabang ini dan memindahkannya ke tempat lain, Anda dapat memotong masing-masingnya, sehingga Anda membuat 1 juta potongan, atau Anda memotong tepat sebelum node, sehingga hanya membuat satu potongan (ini adalah perbedaan antara memindahkan file dan direktori).

dadexix86
sumber
4
Anda harus menyertakan bahwa mvpada sistem file yang sama hanyalah menulis ulang entri TOC.
Videonauth
Saya tidak yakin bahwa saya mengerti apa yang Anda maksud dengan TOC. Sejauh yang saya tahu, tidak ada tabel dalam sistem file ext, atau NTFS, atau btrfs dan sebagainya. FAT memiliki tabel (dari mana ia mengambil nama) tetapi misalnya ext menyimpan nama dan blok, dan orang tua, dan anak-anak dan informasi lainnya dalam inode. Jika Anda dapat mengarahkan saya ke beberapa referensi di mana dijelaskan di mana ext FS memiliki TOC mereka dan untuk apa digunakan, saya dengan senang hati akan membaca dan memperbarui jawabannya :)
dadexix86
10
Um mv *.jpgkemungkinan gagal untuk 12 juta file yang mengapa ia menggunakan find. Kebanyakan Unix, Linux termasuk saya percaya (kecuali seseorang mengubahnya dalam 5-10 tahun terakhir) memiliki panjang maksimum terbatas dari baris perintah. Saya pikir itu 64K untuk Linux untuk waktu yang lama. Batas yang sama berlaku untuk variabel lingkungan, saya cukup yakin.
Zan Lynx
1
Memindahkan file lebih lanjut tentang memindahkan namanya . Entri direktori seperti Unix berisi nama file dan nomor inode, yang pada dasarnya adalah pointer ke seluruh metadata. Direktori hanyalah jenis file khusus. Inode itu sendiri tidak mengandung data aktual dari file, hanya menunjuk ke sana, jadi agak menyesatkan untuk mengatakan bahwa apa pun dipindahkan dari inode. Di sisi lain, jurnal sistem file biasanya merujuk pada jenis log metadata yang sebagian besar digunakan untuk pemeriksaan kerusakan.
ilkkachu
1
Tentu saja, terminologi bukanlah titik utama di sini. Bit penting adalah persis apa yang Anda katakan: di dalam sistem file, suatu langkah hanya perlu menyentuh metadata. Dari satu sistem file ke yang lain, tidak ada jalan pintas dan semua file harus dipindahkan (diciptakan kembali) satu per satu, termasuk kontennya. Dalam hal ini tidak masalah jika seseorang memindahkan seluruh direktori atau hanya file-file di dalamnya, itu akan menjadi lambat.
ilkkachu
13

Masih lambat karena, seperti disebutkan, sistem file harus menghubungkan kembali setiap nama file ke lokasi barunya.

Namun, Anda dapat mempercepatnya dari apa yang Anda miliki sekarang.

Perintah find Anda menjalankan exec sekali untuk setiap file. Jadi itu meluncurkan mvperintah 12 juta kali untuk 12 juta file. Ini dapat ditingkatkan dengan dua cara.

  • Tambahkan nilai tambah di akhir:
    find -maxdepth 1 -name '*.jpg' -exec mv -t ../../dst/ +
    Periksa halaman manual untuk memastikan itu didukung di versi Anda find. Efeknya harus menjalankan serangkaian mvperintah dengan nama file sebanyak yang sesuai pada setiap baris perintah.

  • Gunakan finddan xargsbersama - sama.
    find -maxdepth 1 -name '*.jpg' -print0 | xargs -0 mv -t ../../dst/
    The -print0akan menggunakan NUL, alias nol byte untuk memisahkan nama file. Ini plus xargs -0memperbaiki masalah yang xargsseharusnya ada dengan spasi dalam nama file. The xargsperintah akan membaca daftar nama file dari findperintah dan menjalankan mvperintah pada banyak nama file sebagai muat.

Zan Lynx
sumber
7

Kebingungan Anda berasal dari abstraksi sistem file yang membuat Anda percaya bahwa folder berisi file dan folder lain dengan cara seperti pohon. Ini sebenarnya tidak benar: semua file dan direktori dalam sistem file terletak pada level yang sama dan diidentifikasi dengan beberapa jenis, tergantung pada implementasi. Direktori hanyalah file khusus yang berisi daftar file lain.

Ketika Anda "memindahkan" file di dalam sistem file, file yang sebenarnya tidak pergi ke mana pun. Sebaliknya, daftar di dalam direktori diperbarui untuk mencerminkan perubahan.

mv src ../dstmemindahkan entri daftar tunggal dari direktori .ke direktori ../dst, jadi itu cepat.

find -maxdepth 1 -name '*.jpg' -exec mv -t ../../dst/harus memindahkan jutaan entri, jadi lebih lambat. Mungkin berpotensi dipercepat jika Anda memanggil mvhanya sekali dan tidak sekali per file, dan mvperintah itu sendiri dapat dioptimalkan untuk memindahkan beberapa entri direktori dalam satu langkah, tetapi tidak ada cara untuk membuatnya secepat ketika Anda memindahkan direktori tunggal .

Dmitry Grigoryev
sumber
4

Jawaban yang disederhanakan

Memindahkan file yang dilakukan adalah 3 langkah:

  • tambahkan () tautan ke file ke daftar inode folder tujuan
  • periksa apakah tautan berhasil ditambahkan
  • hapus () tautan dari daftar inode folder sumber jika pemeriksaan di atas berhasil.

proses ini sama untuk file atau folder.
dan jelas melakukan ini untuk 1 file adalah 100 lebih cepat daripada melakukannya untuk 100 file.

man link adalah add ()
man unlinkadalah remove ()
mvhanya menggunakan dua perintah di atas dan menambahkan tanda centang di antara untuk mencegah hilangnya data.


sumber
1
Nah, ada juga ganti nama ().
ilkkachu