GNU/Linux >> Belajar Linux >  >> Linux

Di Linux, apa yang terjadi jika 1000 file dalam direktori dipindahkan ke lokasi lain sementara 300 file lainnya ditambahkan ke direktori sumber?

Ini bergantung pada alat yang Anda gunakan:Mari kita periksa beberapa kasus:

Jika Anda menjalankan sesuatu di sepanjang baris mv /path/to/source/* /path/to/dest/ int sebuah shell, Anda akan berakhir dengan 1000 file asli dipindahkan, 300 file baru tidak tersentuh. Ini berasal dari fakta, bahwa shell akan memperluas * sebelum memulai operasi pemindahan, jadi saat pemindahan sedang berlangsung, daftar sudah diperbaiki.

Jika Anda menggunakan Nautilus (dan teman GUI lainnya), Anda akan berakhir dengan cara yang sama:Nautilus akan menjalankan operasi pemindahan berdasarkan file mana yang dipilih - ini tidak berubah saat file baru muncul.

Jika Anda menggunakan program Anda sendiri menggunakan syscalls di sepanjang garis loop melalui glob dan hanya satu mv hingga glob tetap kosong, Anda akan mendapatkan semua 1300 file di direktori baru. Ini karena setiap glob baru akan mengambil file baru, yang muncul sementara itu.


Saat Anda memberi tahu sistem untuk memindahkan semua file dari direktori, sistem akan mencantumkan semua file dan kemudian mulai memindahkannya. Jika file baru muncul di direktori, file tersebut tidak ditambahkan ke daftar file yang akan dipindahkan, sehingga file tersebut akan tetap berada di lokasi aslinya.

Anda tentu saja dapat memprogram cara memindahkan file yang berbeda dari mv yang secara berkala akan memeriksa file baru di direktori sumber.


Kernel itu sendiri tidak boleh "berada di tengah" dari operasi "pindahkan 1000 file". Anda harus lebih spesifik tentang operasi apa yang Anda usulkan.

Satu utas hanya dapat memindahkan satu file dalam satu waktu dengan rename(*oldpath, const char *newpath) atau renameat panggilan sistem (dan hanya dalam sistem file yang sama). Atau Linux renameat2 yang memiliki bendera seperti RENAME_EXCHANGE untuk menukar dua nama path secara atomik, atau RENAME_NOREPLACE untuk tidak ganti tujuan jika ada. (misalnya mengizinkan mv -i implementasi yang menghindari kondisi balapan dari stat lalu rename , yang masih akan menimpa file yang dibuat setelah stat .link + unlink juga bisa menyelesaikannya, karena link gagal jika ada nama baru.)

Namun setiap panggilan sistem ini hanya mengganti nama satu entri direktori per panggilan sistem . Menggunakan POSIX renameat dengan olddirfd dan newdirfd (dibuka dengan open(O_DIRECTORY) ) akan memungkinkan Anda untuk terus mengulang file dalam direktori meskipun direktori sumber atau tujuan itu sendiri telah diganti namanya. (Menggunakan jalur relatif juga memungkinkan dengan rename() reguler .)

Ngomong-ngomong, seperti jawaban lain, sebagian besar program yang menggunakan rename system call akan mengetahui daftar nama file sebelum melakukan rename pertama . (Biasanya menggunakan readdir(3) Pustaka POSIX berfungsi sebagai pembungkus untuk panggilan sistem khusus platform seperti Linux getdents ).

Tetapi jika Anda berbicara tentang find -exec ... {} \; untuk menjalankan satu perintah per file, atau -exec {} + yang lebih efisien dengan begitu banyak file yang tidak muat di satu baris perintah, maka Anda pasti dapat mengganti nama saat masih memindai. mis.

find . -name '*.txt' -exec mv -t ../txtfiles {} \;   # Intentionally inefficient

Jika Anda membuat beberapa .txt baru file saat ini sedang berjalan, Anda mungkin lihat beberapa di antaranya di ../txtfiles . Tapi secara internal find(1) akan menggunakan open(O_DIRECTORY) dan getdents di . .

Jika satu panggilan sistem sudah cukup untuk mengembalikan semua entri direktori di . (yang find akan mengulang satu per satu, hanya membuat panggilan sistem lebih lanjut jika diperlukan untuk -type atau untuk mengulangi, atau fork+exec pada pertandingan), maka daftar tersebut adalah snapshot dari entri direktori pada satu titik waktu. Perubahan lebih lanjut pada direktori tidak dapat memengaruhi apa find tidak, karena sudah memiliki salinan direktori yang mencantumkan apa yang akan diulang. (Mungkin secara internal menggunakan readdir(3) , yang mengembalikan satu entri pada satu waktu, tetapi di dalam glibc kita tahu dari penggunaan strace find . bahwa itu membuat getdents64 system call dengan ukuran buffer count=32768 entri.)

Tetapi jika direktorinya besar dan/atau kernel tidak mengisi find buffer, itu harus membuat panggilan sistem getdents ke-2 setelah mengulang apa yang didapatnya pertama kali. Jadi mungkin bisa melihat entri baru setelah melakukan beberapa penggantian nama.

Tetapi lihat diskusi dalam komentar di bawah jawaban lain:kernel mungkin telah memotret untuk kami, karena (menurut saya) getdents tidak diizinkan mengembalikan nama file yang sama dua kali. Sistem file yang berbeda menggunakan mekanisme pengurutan / pengindeksan yang berbeda untuk membuat akses ke entri dalam direktori besar lebih efisien daripada pencarian linier. Jadi menambah atau menghapus direktori mungkin memiliki efek lain pada urutan entri yang tersisa. Hmm, mungkin lebih mungkin sistem file mempertahankan urutan yang stabil, dan hanya memperbarui indeks yang sebenarnya (seperti dir_index EXT4 fitur), jadi posisi direktori FD hanya bisa menjadi entri direktori untuk melanjutkan? Saya benar-benar tidak tahu bagaimana telldir(3) antarmuka perpustakaan memetakan ke lseek , atau jika itu murni ruang pengguna untuk mengulang buffer yang diperoleh oleh ruang pengguna. Tapi beberapa getdents dapat diperlukan untuk mendapatkan semua entri dari direktori besar, jadi meskipun pencarian tidak didukung, kernel harus dapat merekam posisi saat ini.

Catatan kaki 1:

Untuk "berpindah" di antara sistem file, terserah ruang pengguna untuk menyalin dan memutuskan tautan. (misalnya dengan open dan read+write , mmap+write atau sendfile(2) atau copy_file_range(2) , dua yang terakhir benar-benar menghindari memantulkan data file melalui ruang pengguna.)


Linux
  1. Apa saja Jenis Shell yang Berbeda di Linux?

  2. Apa itu file jarang di Linux

  3. Apa kerugian dari antrian pesan Linux?

  1. Apa sumber kernel Linux saat ini?

  2. Di mana direktori sementara di Linux?

  3. Apa cara tercepat untuk memindahkan sejuta gambar dari satu direktori ke direktori lain di Linux?

  1. Apa yang seharusnya menjadi izin direktori home yang ideal di linux

  2. Apa sebenarnya header kernel Linux itu?

  3. Hirarki file Linux - apa lokasi terbaik untuk menyimpan file kunci?