Newsgroup: it.comp.os.linux.iniziare
Titolo: Piccolo divertissement su redirezioni (ehm... e non solo) in bash

Per principianti.
 
Pigliamo un comando che produca sia output sia errori. Per esempio:
 
$ ls esiste nonesiste
 
quando il file "esiste" esista davvero, e il file "nonesiste" non esista.
 
Normalmente il comando ls stampa sul terminale sia l'output sia gli 
errori:
 
lem@biggy:/tmp$ ls esiste nonesiste
ls: impossibile accedere a nonesiste: File o directory non esistente
esiste
 
 
1) Lo si modifichi in modo che soddisfi contemporaneamente queste 
condizioni:
 
a) invii l'output sia sul file out1 sia sul file out2;
b) invii gli errori sia sul file err1 sia sul file err2;
c) invii sia l'output sia gli errori sul file both.
d) non stampi alcunché a terminale.
 
2) Ora si modifichi la soluzione del punto 1) in modo che l'output e gli 
errori vengano anche stampati a terminale.
 
Se vi va, buon divertimento. :)
-- 
Bye, Lem
Ceterum censeo ISLAM esse delendum
_________________________________________________________________
Non sprecare i cicli idle della tua CPU, né quelli della tua GPU.
 
http://www.worldcommunitygrid.org/index.jsp
 
http://www.rnaworld.de/rnaworld/
 
http://home.edges-grid.eu/home/
 
 
http://www.gpugrid.net/
 

 Per principianti.
 
Aggiungo un aiutino
 
man tee
 
man bash redirection
 
bit bucket

 
 
Se sei d'accordo, per semplificare suggerirei l'uso di bash.
 
-- 
In God we trust. All others must bring data
W. E. Deming

 Se sei d'accordo, per semplificare suggerirei l'uso di bash.
 
Uh? L'idea era quella, come da Subject...  e come da suggerimenti
di mallin.shetland. :)
 
Non dicevo mica di modificare i sorgenti del comando, eh! :)


 Se vi va, buon divertimento. :)
 
Be' a me interessa parecchio questo problema, la redirezione su un file 
la so fare, su DUE no, figurati poi su 2+monitor. Ho solo vaghi ricordi 
di tee, ma non credo che tu qui voglia usare un programma esterno in 
aggiunta a bash.
Insomma potresti postare le risposte? tanto non credo che qualcuno te 
le possa dare se non esperto, e gli esperti ovviamente non rispondono 
per correttezza.
 
-- 
Tanti saluti
 

 Non dicevo mica di modificare i sorgenti del comando, eh! :)
 
Nono è che avevo la finestra del newsreader stretta e non ho visto la
fine del subject :)


 correttezza.
 
Metto uno spoiler. Poi, se come probabile le mie soluzioni sono
migliorabili, anch'io sono interessato ai commenti! :)
 
<spoiler>
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
</spoiler>
 
Prepariamo con:
 
$ cd /tmp
$ touch esiste; rm nonesiste
 
Ok, la risposta al primo quesito è:
 
$ ((ls esiste nonesiste | tee out1 out2 >&3 ) 2> >(tee err1 err2 >&4)) 3>both 4>&3
 
La risposta al secondo quesito è:
 
$ (((ls esiste nonesiste | tee out1 out2 >&3 ) 2> >(tee err1 err2 >&4)) 3>&1 4>&3) 1> >(tee both)


 </spoiler>
 
La tua era questa (c'ho tolto le quote)
 
$ (((ls esiste nonesiste | tee out1 out2 >&3 ) 2> >(tee err1 err2 >&4)) \
3>&1 4>&3) 1> >(tee both)
 
Propongo quest'altra:
$: ls esiste nonesiste 2> >(tee err1 err2) 1> >(tee out1 out2) | tee tutto
 
-- 
Tanti saluti
 

 tutto
 
Ti dico subito che la tua soluzione mi pare bella e lineare.
 
E basta che tu le metta un ">/dev/null" in fondo, che scompare la stampa 
a schermo e così ottieni una soluzione anche per il punto 1). In questo 
caso, però, lo svantaggio è che, così facendo, anche per la soluzione del 
punto 1) useresti tre tee, come per il punto 2), mentre io per il punto 
1) ne ho usati solo due.
 
Insomma: la tua soluzione per il punto 2) mi pare sotto tutti i punti di 
vista più bella della mia, ed il motivo per cui io non ci sono arrivato 
spero sia solo dato dal fatto che sono partito dalla soluzione del punto 
1) e l'ho modificata. L'altro motivo possibile è che io mi sia un po' 
_tanto_ rimbecillito... ma speriamo di no. ;)
 
 
Già che ci siamo, ricordiamo che invece una soluzione teoricamente 
possibile, ma che *NON* funziona bene, è questa:
 
$ ls esiste nonesiste 2> >(tee err1 err2 >both) 1> >(tee out1 out2 >both)
 
Come si può vedere, la doppia redirezione su file s'accavalla, e il file 
both non viene bene (manca "ls: imp"):
 
$ cat both
lem@biggy:/tmp$ cat both
esiste
ossibile accedere a nonesiste: File o directory non esistente


>both


> ossibile accedere a nonesiste: File o directory non esistente
 
Scusa è venuto male, intendevo append to both >>both


 1) ne ho usati solo due.
 
Cosi' redirigo prima, usando solo due tee:
 
$: > tutto ls pippo xxx 2> >(tee e1 e2) 1> >(tee a1 a2)
 
Tra parentesi: non so perche' ma messo prima va messo dopo no, boh!
 
-- 
Tanti saluti
 

 terminale non lo usano praticamente mai, sanno solo cliccare.
 
Questo si chiama "analfabetismo di ritorno"... :-)
 
bye,
 
-- 
 
piergiorgio

 non so perche' ma messo prima va messo dopo no, boh!
 
Va anche messo dopo, basta che usi le parentesi:
 
$: (ls pippo xxx 2> >(tee e1 e2) 1> >(tee a1 a2)) > tutto
 
In sostanza, quel che redirige il > al di fuori delle parentesi (o quello 
messo prima del comando, è lo standard output dei due tee.
 
In sostanza: le redirezioni si leggono in quest'ordine:
 
a) a livelli: prima quelle fuori dalla parentesi, poi quelle interne alle 
parentesi;
b) quando sono allo stesso livello, da sinistra a destra;
b1) | prima di ogni altra redirezione al medesimo livello, 
indipendentemente dalla posizione (ecco perché con | funziona anche senza 
parentesi!).


 parentesi!).
 
Si' certo, adesso si spiega, ed e' proprio questo che bisogna 
capire/tenere presente, benissimo!
 
PS. Vabbe' che la firma e' sacra, pero' guarda che il latino tuo e' 
arcaico, adesso si dice: "Ceterum censeo VINDOVM esse delendum".
 
-- 
Tanti saluti
 

 Ti dico subito che la tua soluzione mi pare bella e lineare.
 
PUTTANATE!
È contorta e arzigogolata; basta:
 
ls esiste nonesiste 2> >(tee due >/dev/null) | tee uno 
 
La redirezione su /dev/null è necessaria altrimenti verrà rediretto 
nella pipe anche  lo standard error  e non si riuscirà a separare i 
due flussi. 
 
 

 ls esiste nonesiste 2> >(tee due >/dev/null) | tee uno
 
ATTENZIONE!
 
Non credo sia portabile. Anzi credo che verrà etichettata come un
/bashism/ dai veri esperti. O peggio.
 
 

 ls esiste nonesiste 2> >(tee due >/dev/null) | tee uno
 
PUTTANATA!
 
ls esiste nonesiste 2>&1 >/dev/null | tee uno > due
 
 
-- 
Cio' che si vede, e'.
 

zitto coglione

 ls esiste nonesiste 2> >(tee due >/dev/null) | tee uno
 
Ovviamente sono possibile tutte le variazioni:
 
ls esiste nonesiste 2> >(tee due due.bis >due.ter) | tee uno ... 
 
 
 

 zitto coglione
 
Sei ancora piu' idiota di quel che credevo.


Addi' 13 mag 2012, Marco scrive:

Guarda che le uniche finora son quelle di Len Novantotto e le mie, 
deve NON vedersi nulla nel monitor (primo caso), cioe' con questa:
 
$: > tutto ls esiste nonesiste 2> >(tee err1 err2) 1> >(tee out1 out2)
 
e vedersi tutto, cioe' SIA stderr SIA stdout, con quest'altra per il 
secondo caso:
 
$: ls esiste nonesiste 2> >(tee err1 err2) 1> >(tee out1 out2) | tee tutto
 
Non credo si possano abbreviare, anche perche' fanno solo l'essenziale, 
ormai il significato del bellissimo "2> >()" e' chiaro no? cmq tentar 
non nuoce...
 
-- 
Tanti saluti
 

 ls esiste nonesiste 2> >(tee due >/dev/null) | tee uno
 
Questa roba che hai scritto qui sopra non ha alcun senso:
 
a) ovviamente non stampa nulla su both (o tutto, o come lo vogliamo 
chiamare), quindi non risponde ai requisiti;
b) fa esattamente la stessa cosa di:
 
$ ls esiste nonesiste 2> due | tee uno
 
essendo ben più arzigogolata.



Quello che ho postato io non stampa nulla a monitor. Lo hai provato?


 Quello che ho postato io non stampa nulla a monitor. Lo hai provato?
 
La tua, che ho lasciato in quota, produce questo:
- non stampa nulla a monitor, e va bene per il primo caso richiesto;
- crea il file "uno" con lo stderr, e va bene;
- crea il file "due" che NON va, perche' contiene ancora lo stderr!
 
In altre parole, l'ultima redirezione dirotta lo stderr sul file "due" 
invece di visualizzarlo, ma lo stdout se n'e' gia' andato in null, non 
arriva a tee.
 
-- 
Tanti saluti
 


Che e' quello che richiede il caso 1-b. Errori che vanno sia a uno che a
due.


 errori vengano anche stampati a terminale.
 
Quale delle quattro?


 > condizioni:
 
Ok, mea culpa, non ho visto il "contemporaneamente"!


 due.
 
Veramente no. :)
 
Ci sono *tre* (tipi di) file: uno per l'output, uno per gli errori, e il 
terzo (tipo) per entrambi.


 Ok, mea culpa, non ho visto il "contemporaneamente"!
 
:)


 Se vi va, buon divertimento. :)
 
Ok, ora che ho capito. Senza usare il costrutto >() di bash:
 
caso 1)
 
{ { ls esiste nonesiste 2>&3 | tee out1 out2 >&4 ; } 3>&1 | tee err1 err2; } 3>&2 4>&1 | tee both > /dev/null
 
$ cat out*
esiste
esiste
$ cat err*
ls: cannot access nonesiste: No such file or directory
ls: cannot access nonesiste: No such file or directory
$ cat both
ls: cannot access nonesiste: No such file or directory
esiste
 
caso 2)
 
Ovviamente, come 1) pero' togliendo l'ultima ridirezione a /dev/null.
 
{ { ls esiste nonesiste 2>&3 | tee out1 out2 >&4 ; } 3>&1 | tee err1 err2; } 3>&2 4>&1 | tee both
ls: cannot access nonesiste: No such file or directory
esiste
$ cat out*
esiste
esiste
$ cat err*
ls: cannot access nonesiste: No such file or directory
ls: cannot access nonesiste: No such file or directory
$ cat both 
ls: cannot access nonesiste: No such file or directory
esiste


 esiste
 
Scusa ma cosa c'hai contro questo >() ? non fosse altro e' molto piu' 
facile da gestire oltre che brevissimo, guarda:
 
$: > tutto ls pippo xxx 2> >(tee e1 e2) 1> >(tee a1 a2)
$:
$: head *
 
==> a1 <==
pippo
 
==> a2 <==
pippo
 
==> e1 <==
/bin/ls: impossibile accedere a xxx: File o directory non esistente
 
==> e2 <==
/bin/ls: impossibile accedere a xxx: File o directory non esistente
 
==> pippo <==
 
==> tutto <==
/bin/ls: impossibile accedere a xxx: File o directory non esistente
pippo
 
 
P.S. Mi sai dire perche' il tuo ls dice "ls:" invece di "/bin/ls:" ?
 
-- 
Tanti saluti
 

 P.S. Mi sai dire perche' il tuo ls dice "ls:" invece di "/bin/ls:" ?
 
Non ne ho idea!


 Non ne ho idea!
 
In realta' si', dovrebbe essere che il tuo ls e' un alias a /bin/ls
qualcosa.


Addi' 13 mag 2012, Marco scrive:

Vero! se do \ls mi dice "ls:".
C'ho messo il fondamentale -v all'antica, se no non ci capisco nulla:
 
alias ls='/bin/ls -v --group-directories-first --color=auto'
 
-- 
Tanti saluti
 

 chiamare), quindi non risponde ai requisiti;
 
È solo una prova di concetto. Comunque se vuoi una soluzione completa:
 
ls pluto pippo 2> >(tee due >tutto) | tee uno >> tutto
 
E se vuoi anche l'output a terminale:
 
ls pluto pippo 2> >(tee due /dev/tty >tutto) | tee uno dev/tty >> tutto
 
 
 


wrote:

Continui a non capire un cazzo (e non per malafede, temo). Io mi ero
sbagliato e l'ho ammesso.


 ls pluto pippo 2> >(tee due /dev/tty >tutto) | tee uno /dev/tty >> tutto
 
Ecco, grassie! :)


 nulla, sigh! :(
 
Ed hai ragione. Sob :-(((

 Continui a non capire un cazzo
 
Infatti, essendo eterosessuale, mi intendo solo di zizze e di fiche.