GNU/Linux >> Linux Esercitazione >  >> Linux

In Linux cosa succede se 1000 file in una directory vengono spostati in un'altra posizione mentre altri 300 file vengono aggiunti alla directory di origine?

Questo dipende dagli strumenti che utilizzi:controlliamo alcuni casi:

Se esegui qualcosa sulla falsariga di mv /path/to/source/* /path/to/dest/ in una shell, ti ritroverai con i 1000 file originali spostati, mentre i nuovi 300 non verranno toccati. Ciò deriva dal fatto che la shell espanderà il * prima di iniziare l'operazione di spostamento, quindi quando lo spostamento è in corso, l'elenco è già fissato.

Se usi Nautilus (e altri amici della GUI), finirai allo stesso modo:eseguirà l'operazione di spostamento in base ai file selezionati - questo non cambia quando vengono visualizzati nuovi file.

Se usi il tuo programma usando chiamate di sistema lungo la linea del ciclo su glob e solo uno mv fino a glob rimane vuoto, ti ritroverai con tutti i 1300 file nella nuova directory. Questo perché ogni nuovo glob raccoglierà i nuovi file, che sono comparsi nel frattempo.


Quando dici al sistema di spostare tutti i file da una directory, elenca tutti i file e quindi inizia a spostarli. Se nella directory vengono visualizzati nuovi file, non vengono aggiunti all'elenco dei file da spostare, quindi rimarranno nella posizione originale.

Ovviamente puoi programmare un modo di spostare i file diverso da mv che verificherà periodicamente la presenza di nuovi file nella directory di origine.


Il kernel stesso non può essere "nel mezzo" di un'operazione di "spostamento di 1000 file". Devi essere molto più specifico su quale operazione stai proponendo.

Un thread può spostare solo un file alla volta con il rename(*oldpath, const char *newpath) o renameat chiamate di sistema (e solo all'interno dello stesso filesystem). O Linux renameat2 che ha flag come RENAME_EXCHANGE per scambiare atomicamente due nomi di percorso, o RENAME_NOREPLACE non sostituire la destinazione se esiste. (ad es. consentendo un mv -i implementazione che evita la race condition di stat e poi rename , che sovrascriverebbe comunque un file creato dopo stat .link + unlink potrebbe anche risolverlo, perché link fallisce se il nuovo nome esiste.)

Ma ognuna di queste chiamate di sistema rinomina solo una singola voce di directory per chiamata di sistema . Usando POSIX renameat con olddirfd e newdirfd (aperto con open(O_DIRECTORY) ) ti permetterebbe di continuare a scorrere i file in una directory anche se la directory di origine o di destinazione stessa era stato rinominato. (L'utilizzo di percorsi relativi potrebbe anche consentirlo con il normale rename() .)

Ad ogni modo, come dicono le altre risposte, la maggior parte dei programmi che usano la chiamata di sistema rinomina troveranno un elenco di nomi di file prima di eseguire il primo rename . (Di solito usando il readdir(3) Funzione della libreria POSIX come wrapper per chiamate di sistema specifiche della piattaforma come Linux getdents ).

Ma se stai parlando di find -exec ... {} \; per eseguire un comando per file, o il più efficiente -exec {} + con così tanti file che non si adattano a una riga di comando, è possibile che si verifichino rinominazioni durante la scansione. ad esempio

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

Se hai creato un nuovo file .txt mentre era in esecuzione, potresti vederne alcuni in ../txtfiles . Ma internamente find(1) avrà usato open(O_DIRECTORY) e getdents su . .

Se una chiamata di sistema fosse sufficiente per restituire tutto le voci della directory in . (che find eseguirà il loop uno alla volta, effettuando solo ulteriori chiamate di sistema se necessario per -type o per ricorrere, o fork+exec su una corrispondenza), quindi l'elenco è un'istantanea delle voci della directory in un determinato momento. Ulteriori modifiche alla directory non possono influenzare ciò che find fa, perché ha già una copia della directory che elenca ciò su cui eseguirà il ciclo. (Probabilmente utilizza internamente readdir(3) , che restituisce una voce alla volta, ma all'interno di glibc lo sappiamo dall'uso di strace find . che fa un getdents64 chiamata di sistema con una dimensione del buffer di count=32768 voci.)

Ma se la directory è enorme e/o il kernel non riempie find 's buffer, dovrà effettuare una seconda chiamata di sistema getdents dopo aver ripetuto in loop ciò che ha ottenuto la prima volta. Quindi potrebbe forse vedere nuove voci dopo aver fatto alcune rinominazioni.

Ma vedi la discussione nei commenti sotto altre risposte:il kernel potrebbe aver fatto un'istantanea per noi, perché (penso) getdents non è autorizzato a restituire lo stesso nome file due volte. Diversi filesystem utilizzano diversi meccanismi di ordinamento / indicizzazione per rendere l'accesso a una voce in una directory enorme più efficiente di una ricerca lineare. Quindi l'aggiunta o la rimozione di una directory potrebbe avere altri effetti sull'ordine delle voci rimanenti. Hmm, probabilmente è più probabile che i filesystem mantengano un ordine stabile e aggiornino semplicemente un indice effettivo (come EXT4 dir_index caratteristica), quindi la posizione di una directory FD può essere solo una voce di directory da cui riprendere? Davvero non so come il telldir(3) l'interfaccia della libreria è mappata su lseek , o se è puramente una cosa dello spazio utente per eseguire il looping sul buffer ottenuto dallo spazio utente. Ma più getdents può essere necessario per ottenere tutte le voci da una directory enorme, quindi anche se la ricerca non è supportata, il kernel deve essere in grado di registrare una posizione corrente.

Nota 1:

Per "spostarsi" tra i filesystem, spetta allo spazio utente copiare e scollegare. (ad es. con open e read+write , mmap+write o sendfile(2) o copy_file_range(2) , gli ultimi due evitano totalmente di far rimbalzare i dati del file attraverso lo spazio utente.)


Linux
  1. Linux:quali sono i diversi modi per impostare i permessi dei file ecc. su Gnu/linux?

  2. Cosa sono i file sparsi in Linux

  3. Cosa succede a un handle di file aperto su Linux se il file puntato viene spostato o eliminato

  4. Quali sono le differenze tra lsof e netstat su Linux?

  5. Qual è l'equivalente di Active Directory su Linux

Percorso assoluto vs relativo in Linux:qual è la differenza?

Dov'è la directory temporanea in Linux?

Qual è il modo più veloce per spostare un milione di immagini da una directory all'altra in Linux?

Quali dovrebbero essere i permessi ideali della home directory in Linux

Quali sono i diversi modi per impostare i permessi dei file ecc. su gnu/linux

Cosa significa il suffisso .d in Linux?