Per espandere la risposta di @Alex Gitelman:sì, c'è una differenza tra "input standard" e riga di comando.
Quando digiti rm a.txt b.txt c.txt
, i file elencati dopo rm
sono noti come argomenti e sono resi disponibili a rm tramite una variabile speciale (chiamata argv
internamente). Lo standard input, d'altra parte, sembra a un programma Unix come un file chiamato stdin
. Un programma può leggere i dati da questo "file" proprio come farebbe se aprisse un normale file su disco e leggesse da quello.
rm
, come molti altri programmi, prende i suoi argomenti dalla riga di comando ma ignora l'input standard. Puoi convogliare qualsiasi cosa ti piaccia; getterà via quei dati. Ecco dove xargs
torna utile. Legge le righe sullo standard input e le trasforma in argomenti della riga di comando, in modo da poter reindirizzare efficacemente i dati alla riga di comando di un altro programma. È un bel trucco.
Ad esempio:
find . -name ".txt" | xargs rm
find . -name ".txt" | grep "foo" | xargs rm
Nota che questo funzionerà in modo errato se ci sono nomi di file contenenti newline o spazi. Per gestire nomi di file contenenti newline o spazi dovresti usare invece:
find . -name ".txt" -print0 | xargs -0 rm
Questo dirà find
per terminare i risultati con un carattere null invece di una nuova riga. Tuttavia, grep
non funzionerà come prima allora. Usa invece questo:
find . -name ".txt" | grep "foo" | tr "\n" "\0" | xargs -0 rm
Questa volta tr
viene utilizzato per convertire tutte le nuove righe in caratteri nulli.
"perché non riesco a reindirizzare find result a rm?"
Quando invii qualcosa a un programma, la pipe sostituisce l'input da tastiera. Tienilo a mente e poniti la domanda successiva:cosa farebbe rm
fare con una tastiera? Eliminare le sequenze di tasti? (un po' sciocco davvero) Accettare il controllo interattivo? (rm
non è interattivo tranne a volte quando ha bisogno di conferma, che in effetti può essere data da una pipe.)
Infatti, quando rm
è già in esecuzione, non puoi digitare comandi per consentirgli di eliminare i file... quindi non puoi farlo neanche con una pipe.
Se tieni presente che una pipe sostituisce la combinazione tastiera/schermo, le cose sembreranno immediatamente più logiche.
Ora viceversa. Puoi convogliare un flusso di dati in grep
.Questo significa che puoi consentire a grep di leggere i tasti premuti dalla tua tastiera come dati di input?
SÌ! Questo è effettivamente ciò che fa nativamente (senza piping).
(a proposito, nota che non puoi reindirizzare né digitare l'argomento di ricerca in grep
)
Quindi ora sai perché non puoi pipe a rm e aspettati che funzioni come argomento della riga di comando.
tl;dr :
Anatomia di un programma secondo la filosofia UNIX:
file in, file out, tastiera in, screen out. -> Pipe sostituisce solo tastiera e schermo.
Pipe invia l'output del primo comando allo standard input del secondo. rm
non accetta l'input standard, quindi non è possibile reindirizzarlo. Potresti usare xargs
per ottenere lo stesso effetto. Puoi trovare un esempio per xargs
specificamente per il tuo caso nella pagina man di xargs.