Quali sono le differenze tra &> e 2> & 1


30

Ci sono due forme di reindirizzamento del livello di output e standard error in standard output . Ma quale è meglio? e perché &>è considerato il perfetto?

Non riesco a trovare le differenze in modo che molti tutorial e persino bash manuale affermino che &>è meglio!

Quindi, perché dovrei usare &>e non2>&1

Principalmente usando la bashshell


EDIT: Grazie per i commentatori

Solo> & funziona in csh o tcsh

In ksh funzionano solo 2> & 1.

trattino usa> file 2> & 1 solo reindirizzamento

Quindi quale usare per garantire che il mio script sia compatibile con altri sistemi qualunque siano le shell utilizzate!


il migliore è quello che fa quello che devi fare. questi fanno cose molto diverse. quale shell stai usando?
Skaperen,

@Skaperen utilizzando bash
Maythux l'

1
che cosa si vuole realizzare?
Skaperen,

Voglio solo sapere quali sono le differenze, quello che voglio non è in entrambi, ma devo solo sapere se c'è una differenza in modo che una volta si preferisca alle altre
Maythux,

2
&> somewhereè solo una scorciatoia per bash > somewhere 2>&1: nelle parole del manuale bash, sono "equivalenti in modo simmetrico"
steeldriver,

Risposte:


23

La pagina man di Bash menziona due modi per reindirizzare stderr e stdout : &> file e >& file. Ora, nota che dice sia stderr che stdout.

In questo caso >file 2>&1stiamo eseguendo il reindirizzamento di stdout (1) su file, ma poi anche dicendo a stderr (2) di essere reindirizzato nello stesso posto di stdout! Quindi lo scopo può essere lo stesso, ma l'idea è leggermente diversa. In altre parole "John, vai a scuola; Suzzie vai dove John va".

Che dire delle preferenze? &>è una bashcosa. Quindi, se stai eseguendo il porting di uno script, questo non lo farà. Ma se sei sicuro al 100% che il tuo script funzionerà solo sul sistema con bash - allora non c'è preferenza

Ecco un esempio con dash, Debian Amquist Shell, che è l'impostazione predefinita di Ubuntu.

$ grep "YOLO" * &> /dev/null
$ grep: Desktop: Is a directory
grep: Documents: Is a directory
grep: Downloads: Is a directory
grep: Music: Is a directory
grep: Pictures: Is a directory
grep: Public: Is a directory
grep: Templates: Is a directory
grep: Videos: Is a directory
grep: YOLO: Is a directory
grep: bin: Is a directory

Come puoi vedere, stderr non viene reindirizzato

Per rispondere alle tue modifiche alla domanda, puoi usare l'istruzione if per controllare la variabile $ SHELL e modificare i reindirizzamenti di conseguenza

Ma per la maggior parte dei casi > file 2>&1dovrebbe funzionare


In termini più tecnici, il modulo [integer]>&wordsi chiama Duplicating Output File Descriptor ed è una funzione specificata dallo standard POSIX Shell Command Language Language, che è supportato dalla maggior parte delle shell conformi a POSIX e simili a Brourne.

Vedi anche Cosa significa esattamente nel reindirizzamento dell'output?


Quindi cosa succede quando si utilizza su altre shell?
Maythux,

zsh supporta &>.... @Maythux Nelle shell che non supportano, &>ad esempio, dashè necessario utilizzare il banale >file 2>&1reindirizzamento ..
heemayl

Quindi quale usare se voglio essere sicuro che il mio script sarà compatibile con diverse shell
Maythux,

3
@Maythux Use >file 2>&1. Questo lavoro su tutte le conchiglie
Sergiy Kolodyazhnyy l'

1
@ TSJNachos117 le shell impostate /etc/passwdper ogni utente sono shell interattive. Gli script di sistema sono generalmente dash previsti se non diversamente specificato. Per quanto riguarda ciò che è predefinito, è determinato da ciò che è collegato al /bin/shcaso di Ubuntu dash. In RHEL lo è bash, in FreeBSD è tcsh fonte e un'altra fonte
Sergiy Kolodyazhnyy,

7

In genere consiglierei di seguire il modo di fare le cose di Bourne-again SHell , dato che bash è probabilmente la shell Unix più popolare in circolazione. Bash usa tipicamente &>o 2>&1. IMHO, nessuno dei due è "perfetto", quindi consiglio di dimenticare questa assurdità. Realisticamente, quale dovresti usare dipende da cosa stai cercando di fare.

2>&1unisce stderr a stdout, che può essere utile se, ad esempio, si desidera reindirizzare il testo stderr. Quindi, ad esempio, se vuoi vedere se un programma stampa un certo messaggio stderr, ma non vuoi che lo schermo sia pieno di immondizia (presumibilmente) non importante, potresti fare qualcosa del genere program 2>&1 | grep crashed, che cercherà lo stdout e lo stderr da un programma chiamato "programma" per la parola "crash".

D'altra parte, se non vuoi che un programma stampi qualcosa, puoi semplicemente eseguirlo program &> /dev/null, che reindirizzerà sia stderr che stdout a / dev / null, un file speciale che magicamente fa sparire le cose. Oppure, se si desidera salvare l'output di un programma (forse per segnalare un bug o qualcosa del genere), è possibile reindirizzare sia stderr che stdout su un file: program &> log.txtreindirizzerà tutti i dati su un file chiamato "log.txt". Se lo desideri, puoi reindirizzare lo stdout e lo stderr tramite program 2> log.txt > log.txto program 2>&1 | cat > log.txt, entrambi i quali avrebbero lo stesso effetto dell'utilizzo &>. Se fai qualcosa del genere program 2>&1 > file, solo lo stdout verrà reindirizzato, ma lo stderr può comunque essere reindirizzato a un altro programma, come cat, che potrebbe essere reindirizzato come mostrato sopra. Tuttavia, digitando&>è più semplice di tutti gli esempi precedenti, poiché comporta la digitazione di un minor numero di caratteri (ed è un po 'più facile da leggere per gli esseri umani). Nota che program 2> log.txt > log.txtpotrebbe essere più probabile che funzioni su shell non bash.

PS: se sei preoccupato per le persone che usano altre shell, c'è qualcosa che puoi aggiungere per essere la prima riga della tua sceneggiatura chiamata "numero magico", o "shebang". Questo è essenzialmente un modo per assicurarsi che altri computer (in particolare quelli che eseguono sistemi operativi simili a Unix) sappiano quale programma usare per eseguire uno script. Script diversi usano shebang diversi. Un shebang per uno script bash è simile al seguente:

#!/bin/bash

Se usi quanto sopra come prima riga di un determinato script, bash verrà generalmente usato per eseguire detto script. Ciò renderà molto più difficile per qualcuno eseguire accidentalmente lo script con la shell sbagliata.

PS: Non mentirò: fino ad ora, non sapevo che si potesse usare >&, ma, per quanto riguarda Bash, sembra che faccia lo stesso &>. Si impara qualcosa di nuovo ogni giorno.


Mentre sono d'accordo con te sull'uso della #!linea per richiedere esplicitamente bash, non è sempre disponibile su altri sistemi. Molto spesso gli sviluppatori / amministratori di sistema devono scrivere script portatili per i sistemi su cui bashpotrebbe non essere disponibile e potrebbe non essere sotto il loro controllo per l'installazione bash. Il >file 2>&1è solo molto più portabile.
Sergiy Kolodyazhnyy,

Hai fatto un errore di inversione sopra, che non produce il risultato che rivendichi o desideri. Reindirizzare stderr su stdout, quindi reindirizzare stdout lascia stderr sullo stdout originale.
ubfan1,

Serg: Non intendevo dire che bash fosse universale. Tuttavia, penso che più persone lo stiano usando piuttosto che dire (t) csh. Se non sai cosa sta usando qualcun altro e devi fare un'ipotesi cieca, bash è probabilmente la soluzione migliore. Inoltre, generalmente non conosco la portabilità, poiché utilizzo solo bash. Il fatto che >file 2>&1sia più portatile è buono a sapersi. Farò una modifica per riflettere ciò.
TSJNachos117,

Ubfan1, grazie per le informazioni. In un milione di anni non avrei mai immaginato che bash non avrebbe reindirizzato stderr a un file in quel caso. Ho appena modificato la mia risposta per impedire ad altri di fare lo stesso errore.
TSJNachos117,

4

Dal manuale di riferimento di Bash -> 3.6.4 Reindirizzamento dell'output standard e dell'errore standard :

Questo costrutto consente sia l'output standard (descrittore di file 1) sia l'output di errore standard (descrittore di file 2) da reindirizzare al file il cui nome è l'espansione della parola.

Esistono due formati per il reindirizzamento dell'output standard e dell'errore standard:

&>word

e

>&word

Delle due forme, la prima è preferita. Questo è semanticamente equivalente a

>word 2>&1

Quando si utilizza il secondo modulo, la parola non può espandersi in un numero o "-". In tal caso, si applicano altri operatori di reindirizzamento (vedere Duplicazione dei descrittori di file di seguito) per motivi di compatibilità.

Buono anche a fare riferimento al wiki di Greg su Input & Output -> 4.2. Manipolazione del descrittore di file :

Per comodità, Bash mette a tua disposizione anche un'altra forma di reindirizzamento. L'operatore di reindirizzamento &> è in realtà solo una versione più breve di ciò che abbiamo fatto qui [ 2>&1]; reindirizzare sia stdout che stderr su un file.


4

Quindi perché dovrei usare &> e non 2> & 1

2>&1 è la shell Bourne / POSIX standard.

&>è un'estensione bash e non standard de jure .

Se scrivi script usando le estensioni bash, prima o poi incontrerai errori di grattacapo con messaggi di errore di sintassi criptici perché vengono eseguiti in una shell standard.

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.