L'eco di un comando di coda produce un output imprevisto?


8

Questo comando, quando eseguito da solo, produce il risultato atteso (l'ultima riga del crontab):

tail -n 1 /etc/crontab

Tuttavia, quando lo eseguo come parte di un comando echo per inviare il risultato a un file, viene aggiunto un riepilogo di tutti i file nella directory di lavoro, oltre al risultato previsto:

sudo bash -c 'echo $(tail -n 1 /etc/crontab) > /path/to/file'

Perché questo comando ha prodotto dati extra?



3
Cosa ti sta echofacendo qui? Considera anchetail -n 1 /etc/crontab | sudo tee /path/to/file >/dev/null
ctrl-alt-delor

Risposte:


22

La tua linea crontab ha uno o più asterischi *, che indica "in qualsiasi momento". Quando quella linea viene sostituita dalla sostituzione del comando, il risultato è qualcosa di simile

echo * * * * * cmd > /path/to/file

Mentre la maggior parte delle ulteriori espansioni non vengono applicate all'output della sostituzione del comando, l' espansione del percorso è (come la divisione del campo) :

I risultati della sostituzione dei comandi non devono essere elaborati per un'ulteriore espansione della tilde, espansione dei parametri, sostituzione dei comandi o espansione aritmetica. Se si verifica una sostituzione di comando tra virgolette doppie, la divisione dei campi e l' espansione del percorso non devono essere eseguite sui risultati della sostituzione.

L'espansione del percorso è ciò che si trasforma *.txtin un elenco di nomi di file corrispondenti (globbing), dove *corrisponde a tutto. Il risultato finale è che ottieni tutti i nomi di file (non nascosti) nella directory di lavoro elencati per ognuno *nella tua linea crontab.


Puoi risolvere questo problema citando l'espansione, se il codice che hai pubblicato era un rappresentante di un comando più complesso:

sudo bash -c 'echo "$(tail -n 1 /etc/crontab)" > /path/to/file'

ma più semplicemente perdi del echotutto:

sudo bash -c 'tail -n 1 /etc/crontab > /path/to/file'

Questo dovrebbe fare quello che vuoi ed è anche più semplice (l'unica altra differenza sostanziale è che questa versione ometterà la divisione dei campi che altrimenti si sarebbe verificata, quindi le serie di spazi non verranno compresse).


5
Dal momento che / etc / crontab è quasi sempre leggibile dal mondo, tutto il trucco "bash -c" è in realtà superfluo: tail -n -1 /etc/crontab | sudo tee /path/to/fileè il linguaggio che ho trovato essere il minimo soggetto a errori nel reindirizzare l'output in file che richiedono privilegi di superutente.
Bass

5

Consideriamo una directory con questi file:

$ ls
crontab  file1  file2  file3
$ cat crontab
f*

Ora eseguiamo il comando tail:

$ tail -n 1 crontab
f*

Quanto sopra è l'ultima riga crontabe questo è ciò che ci aspettiamo. Però:

$ echo $(tail -n 1 crontab)
file1 file2 file3

Le virgolette doppie eliminano questo problema:

$ echo "$(tail -n 1 crontab)"
f*

Senza le doppie virgolette, il risultato della sostituzione del comando viene espanso dalla shell. Una delle espansioni è l'espansione del nome percorso . Nel caso sopra, ciò significa che f*viene espanso per corrispondere a tutti i nomi di file che iniziano con f.

A meno che non si desideri esplicitamente espansioni della shell, inserire tutte le variabili della shell e / o le sostituzioni dei comandi tra virgolette doppie.


4

il meccanismo globale di shell si espanderà *in file locale.

la linea crontab probabilmente avrà un *segnaposto per qualsiasi.

ad es. questa linea in crontab funziona alle 7,47 di domenica, prima stella significa ogni giorno, seconda ogni mese.

47  7 * * 0 /run/on/sunday

allora tu tailed emetti

echo 47  7 * * 0 /run/on/sunday

che si espanderà *nel file locale.

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.