Prima di tagliare le risposte banali ma inapplicabili: non posso usare né il trucco find
+ xargs
né le sue varianti (come find
con -exec
) perché ho bisogno di usare poche espressioni del genere per chiamata. Tornerò su questo alla fine.
Ora per un esempio migliore consideriamo:
$ find -L some/dir -name \*.abc | sort
some/dir/1.abc
some/dir/2.abc
some/dir/a space.abc
Come posso passare quelli come argomenti a program
?
Solo farlo non fa il trucco
$ ./program $(find -L some/dir -name \*.abc | sort)
fallisce poiché program
ottiene i seguenti argomenti:
[0]: ./program
[1]: some/dir/1.abc
[2]: some/dir/2.abc
[3]: some/dir/a
[4]: space.abc
Come si può vedere, il percorso con lo spazio è stato diviso e lo program
considera come due argomenti diversi.
Cita fino a quando non funziona
Sembra che gli utenti alle prime armi come me, di fronte a tali problemi, tendano ad aggiungere casualmente le virgolette fino a quando finalmente non funziona - solo qui non sembra aiutare ...
"$(…)"
$ ./program "$(find -L some/dir -name \*.abc | sort)"
[0]: ./program
[1]: some/dir/1.abc
some/dir/2.abc
some/dir/a space.abc
Poiché le virgolette impediscono la divisione delle parole, tutti i file vengono passati come un singolo argomento.
Citando percorsi individuali
Un approccio promettente:
$ ./program $(find -L some/dir -name \*.abc -printf '"%p"\n' | sort)
[1]: "some/dir/1.abc"
[2]: "some/dir/2.abc"
[3]: "some/dir/a
[4]: space.abc"
Le virgolette ci sono, certo. Ma non vengono più interpretati. Sono solo una parte delle stringhe. Quindi non solo non hanno impedito la divisione delle parole, ma hanno anche litigato!
Cambia IFS
Poi ho provato a giocare con IFS
. Preferirei find
con -print0
e sort
con -z
ogni modo - in modo che non abbiano problemi sui "percorsi cablati" stessi. Quindi perché non forzare la divisione delle parole sul null
personaggio e avere tutto?
$ ./program $(IFS=$'\0' find -L some/dir -name \*.abc -print0 | sort -z)
[0]: ./program
[1]: some/dir/1.abcsome/dir/2.abcsome/dir/a
[2]: space.abc
Quindi si divide ancora nello spazio e non si divide su null
.
Ho provato a posizionare il IFS
compito sia in $(…)
(come mostrato sopra) che prima ./program
. Inoltre ho provato altre sintassi del tipo \0
, \x0
, \x00
sia citato con '
e "
così come con e senza $
. Nessuno di quelli sembrava fare la differenza ...
E qui sono senza idee. Ho provato qualche altra cosa, ma tutto sembrava ridursi agli stessi problemi elencati.
Cos'altro potrei fare? È fattibile affatto?
Certo, potrei far program
accettare gli schemi e fare ricerche da solo. Ma è un sacco di doppio lavoro mentre lo fissa su una sintassi specifica. (Che ne dite di fornire file grep
per esempio?).
Inoltre potrei fare program
accettare un file con un elenco di percorsi. Quindi posso facilmente scaricare l' find
espressione in qualche file temporaneo e fornire solo il percorso a quel file. Questo potrebbe essere supportato lungo percorsi diretti in modo che se l'utente ha solo un percorso semplice può essere fornito senza file intermedio. Ma questo non sembra carino - bisogna creare file extra e prendersene cura, per non parlare dell'implementazione extra richiesta. (Sul lato positivo, tuttavia, potrebbe essere un salvataggio per i casi in cui il numero di file come argomenti inizia a causare problemi con la lunghezza della riga di comando ...)
Alla fine, lascia che ti ricordi ancora che i trucchi find
+ xargs
(e simili) non funzioneranno nel mio caso. Per semplicità di descrizione sto mostrando solo un argomento. Ma il mio vero caso è più simile a questo:
$ ABC_FILES=$(find -L some/dir -name \*.abc | sort)
$ XYZ_FILES=$(find -L other/dir -name \*.xyz | sort)
$ ./program --abc-files $ABC_FILES --xyz-files $XYZ_FILES
Quindi fare xargs
una ricerca da una volta mi lascia ancora come affrontare l'altra ...
mapfile
(o sul suo sinonimoreadarray
). Ma funziona!