osx: seleziona selettivamente un numero elevato di file: - @ opzione OK?


4

Devo creare un file zip per l'archiviazione di ~ 100k file da una directory contenente ~ 500k file. Ottengo errori "Elenco argomenti troppo lungo" quando provo i comandi ovvi:

zip archive.zip *pattern*.txt                        # fails
zip archive.zip `find . -name "*pattern*.txt"`       # fails

Un approccio consiste nell'utilizzare l' -@opzione per alimentare un elenco di file tramite via stdin:

find . -name "*pattern*.txt" | zip -@ archive.zip

Tuttavia, la zippagina man dice:

Se un elenco di file viene specificato come - @ [Non su MacOS], zip prende l'elenco dei file di input dall'input standard anziché dalla riga di comando.

È il "Non su MacOS" a infastidirmi. Sono andato avanti e ho provato l' -@opzione, e sembra funzionare; ma mi sento nervoso sul fatto che stia davvero facendo il lavoro giusto (archiviando tutti i file, intatti).

Ecco le mie domande:

  1. Perché -@non andrebbe bene su MacOS?
  2. Esistono alcune versioni di MacOS / bash / zip in cui questo avviso è vero e altre in cui non lo è? È un avvertimento obsoleto e, in tal caso, dov'è la linea di demarcazione?
  3. Quale sarebbe un approccio praticabile per questo problema senza l'utilizzo -@?

Si noti che la soluzione fornita qui zip: Elenco argomenti troppo lungo (80.000 file in totale) non funzionerà; Devo archiviare alcuni, non tutti, i file nella directory.

Sto eseguendo Mac OS 10.7.5. Ecco alcune informazioni sulla versione:

$ bash --version
GNU bash, version 3.2.48(1)-release (x86_64-apple-darwin11)
$ zip --version
This is Zip 3.0 (July 5th 2008), by Info-ZIP.
...
Compiled with gcc 4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2335.15.00) for Unix (Mac OS X) on Jun 24 2011.

Risposte:


6

Prima di tutto,

zip archive.zip `find . -name "*pattern*.txt"`

non è mai una buona idea. I nomi dei file possono contenere spazi, carattere di nuova riga, parti che potrebbero essere interpretate come interruttori e quant'altro.

Per eseguire un'azione per ogni file trovato, è possibile utilizzare l' opzione-exec o xargs .

find . -name "*pattern*.txt" -exec zip archive.zip {} +

aggiungerà i file uno per uno al file zip. Qui, {}simboleggia il file attualmente elaborato.

Terminare l' -execargomento con un +invece di ;cause trova l'elaborazione di più file contemporaneamente (il maggior numero possibile senza generare gli stessi errori che stai ricevendo), che dovrebbe essere considerevolmente più veloce per un gran numero di file.

find . -name "*pattern*.txt" -print0 | xargs -0 zip archive.zip

fa essenzialmente lo stesso. xargs elabora più file contemporaneamente per impostazione predefinita.

Il -print0passaggio per trovare e -0passare a xargs fa sì che utilizzino caratteri null come separatori di file per gestire correttamente nomi di file strani.

Non so il motivo per cui il -@non è raccomandato per Mac OS 1 , ma find ... | zip -@sarà senza gestire strani nomi di file (in particolare, i nomi di file contenenti caratteri di nuova riga) in modo corretto. Questo è vero indipendentemente dal sistema operativo.


1 Sto indovinando questo vale solo per Mac OS fino alla versione 9.x, dal momento che Mac OS utilizzato ritorni a capo personaggi come nuova riga, mentre zip -@si aspetta ritorni a capo.


3

Dennis aveva ragione, è una cosa di OS 9. Ho dato un'occhiata al codice sorgente per Zip 3.0. Nella macos/directory della piattaforma, c'è una nota che dice:

Questa porta è per le versioni Mac precedenti a Mac OS X. Poiché Mac OS X è basato su Unix, utilizzare la porta Unix per Mac OS X. - 7 giugno 2008

Inoltre, il zip.cfile include la dichiarazione dell'opzione della riga di comando in #ifndef MACOS. In altre parole, se avessi eseguito la porta "MacOS" di zip, l' -@opzione semplicemente fallirebbe.

Dennis ha anche fornito la risposta a "un modo praticabile per svolgere il compito senza -@", vale a dire,

find . -name "*pattern*.txt" -print0 | xargs -0 zip archive.zip

Sono d'accordo che questo è il modo migliore di procedere al fine di essere al sicuro da nomi di file "strani" (nomi di file con spazi, righe, ecc.). Tuttavia, vi è una penalità per le prestazioni. xargschiamerà zippiù volte, con una grande serie di nomi di file passati come parametri della riga di comando ogni volta. zipaggiungerà quei file in archive.zipogni invocazione. Ma zipdovrà leggere il sempre più grande archive.zipsu ogni invocazione, che richiede sempre più tempo man mano che il lavoro procede.

Se sai per certo che i nomi dei file in questione non hanno caratteri patologici come spazi o newline, quindi il passaggio singolo

find . -name "*pattern*.txt" | zip -@ archive.zip

sarà più veloce; e funziona perfettamente su OS X, perché zipsu OS X è in realtà la porta Unix. L'avvertimento nella manpage non si applica.


0

Come mostrano le informazioni sulla versione, il codice di base (e quindi presumibilmente la documentazione) è piuttosto vecchio, MacOS nel frattempo è cambiato un po '. Inoltre, la build è molto più recente del codice di base, potrebbero esserci delle modifiche al codice / alla configurazione per la build che non sono mai state inserite nella documentazione.

In ogni caso, controlla meglio (forse con un piccolo esempio) che il comando funzioni e memorizzi davvero i file che gli vengono richiesti. Se è importante, non credere ai quadrati colorati con pezzi mancanti su siti Internet casuali ...

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.