Inputi/Outputi (I/O) ehk sisendi väljundi ümbersuunamine Linuxis

teejuht
 
 
1. Sissejuhatus
2. I/O suunamine kasutamata deskriptoreid 0, 1, 2
3. I/O suunamine kasutades deskriptoreid 0, 1, 2
4. Kokkuvõttev tabel
 

1. Sissejuhatus

Kui veidi järele mõelda siis on tõesti ehk õige väita, et programmil on

- sisend kust sisenevad programmi andmed (tavaliselt saab programm sisendi  klaviatuurilt ehk standard inputist, arv 0)
- väljund mille kaudu väljuvad programmist töödeldud andmed  (tavaliselt lähevad nad monitorile ehk standard output'i, arv 1)
- veaväljund mille kaudu väljuvad programmist veateated (tavaliselt monitorile, mida nimetatakse sel puhul standard error'iks, arv 2)

Linux's saab küllaltki paindlikult prgrammide nn. mulkudesse ja mulkudest tulevaid andmevooge edasi ja ümber suunata. Enamasti on need ümbersuunamised mingi filtreerimise moodi moega aga mitte ainult.

2. I/O suunamine kasutamata deskriptoreid 0, 1, 2
 
 
 
programmi väljundi ümersuunamine
Suuname kalendri ekraanile toova käsu väljundi faili.  
bash# cal 4 1998 > aprill_1998  
(tehes ls ja cat aprill_1998 võib veenduda, et asi toimis)  

suuname väljundi floppy' kettaseadmele  
bash# cal 4 1998 > /dev/fd0  

suuname väljundi kellegi teise terminalile  
bash# cal 4 1998 > /dev/tty3

 
programmi sisendi ümbersuunamine
bash# cat < aprill_1998  
bash# wc < aprill_1998  

tõsi paljud programmid on arvestatud nii, et nende sisend tuleb failist, sestap töötab ka selline variant:  
bash# cat  aprill_1998  
bash# wc  aprill_1998  
 

 
klaviatuurilt ehk standard inputist lugemine
- näitab explicitly tõtta stdin-ist:  
bash# wc -  
tere, mina olen hobune ja hirnun hirmunult  
Ctl+D  
1 7 43 -  
bash #
 
kasutame nüüd nn toru | ühe programmi väljundi teise sisendiga ühendamiseks 
bash# who | wc  
3 15 54  
bash#  
eeldusel, et who väljund on selline  
  
imre tty1 Jun  5 12:40
tanel tty2 Jun  5 12:55
tuuli ttyp0 Jun 5 12:35
tõlgendub wc antud ridade arv kasutajate arvuna süsteemis  
-------------------------------------------------------------------  
Oletame, et kataloogis on palju faile ja me tahame näha vaid niisuguste nimesid kus esineb mingi sõna. Seda saab teha näiteks nii:  

bash# ls -la | grep seesona  
--------------------------------------------------------------------  
Kui aga tahame sarnaselt otsida failist siis teeme nii:  

cat failinimi | grep -n migni_sona  

või  

cat < failinimi | grep -n migni_sona  
-n näitab ära rea numbri kus too mingi_sona oli  
---------------------------------------------------------------------  
vahest on hea read tähestikulises järjekorras sorteerida - käsk sort teeb seda nii:  

tema sisendisse tuleb vaid suunata reavahetustega eraldataud ASCII fail:  

cat minu_fail | sort  

või  

ls | sort  
ls -la | sort +4n 
(viimane peaks sorteerima 5. (viienda!) tulba arvväärtuste järjekorras 
ls -la | sort +8 
nimede järjekorras 
----------------------------------------------------------------------  
kui vaadata pikki tekstifaile on abiks programm more või less. Neid nimetatakse ka pageriteks - nad näitavad teksti ekraanitäite kaupa.  

more failinimi  
less failinimi  

aga samuti, kui on tegemist pika kataloogi listinguga saab neid toru abil kasutada:  

ls -la | more 
ls -la | less

 
 

3. I/O suunamine kasutades deskriptoreid 0, 1 ,2

Nagu algul mainitud on igal programmil olemas nö. kolm mulku:

standard sisend
standard väljund
standard veaväljund

neid märgitakse vastavalt arvudega 0,1, 2

tavaliselt on nad kõik seotud terminaliga (klaviatuur on terminali osa mõnes mõttes), st. sisestusi oodatakse terminalilt (käsurealt juurest) ja väljund (sh. veateated) antakse terminalile.

Vaatame mõnda näidet kuidas saab standartseid nö. andmevooge muuta:
 
1. kaotame ära veateated (see ei tee vigu olematuks!) bash# ls -l sedafailipoletegelikult 
ls: sedafailipoletegelikult: No such file or directory 
bash# 

bash# ls -l sedafailipoletegelikult 2> /dev/null 
bash# 
/dev/null on nö. must auk - kõik mis sinna saata kaob jäljetult 

2. kaotame ära väljundi: bash# ls 1> /dev/null 
bash# 
3. seome kokku ühe programmi väljundi (1) teise sisendiga (0)  bash# ls | wc 
    126     126    1091 
4. ühendame 1 ja 2 voo  nt olgu meil tarvis, et shell script k.sh 

bash# cat k.sh 
#!/bin/sh 
date 
prr 

bash# k.sh 
Wed Jul 29 11:36:31 EST 1998 
./k.sh: prr: command not found 
bash# 

, ei annaks mitte mingisugust väljundit, ei tavalist ei veateateid: 

proovige variante 

bash#k.sh >/dev/null 
./k.sh: prr: command not found 
bash# 

bash#k.sh 1>/dev/null 
./k.sh: prr: command not found 
bash# 

bash#k.sh 2>/dev/null 
Wed Jul 29 11:36:31 EST 1998 
bash# 

bash#k.sh 1>/dev/null 2> &1 
bash# 

viimasele on selline selgitus, et 2 voog on suunatud kokku esimesga ja esimene läheb /dev/null'i 

 
 
4. Kokkuvõttev tabel
 
 
näide
selgitus
> filename
ls -l > kataloogi.sisu suunab programmi standarväljundi (1) faili
>> filename
ls -l >> kataloogi.sisu append'ib (lisab) (1) faili lõppu
< filename
mail -s hallo imre < kiri.ise saadab kirja subj. hallo ja saaja imre
p1 | p2
who | wc ühendab p1 (1) p2 (0) -i
n > &m
k.sh 1>/dev/null 2> &1 ühendab voo 2 1 -ga
<<str
#!/bin/sh 

a=5; 

tr "[a-z]" "[A-Z]" <<mark 
tere kas see on korras? 
ja mida muutuja $a teeb? 
mark 

cat > fail <<mark2 
ja kas see tekst läheb faili? 
mark2 
 

programm saab teksti str nagu oleks see sisestatud klaviatuurilt. 
Praktilist rakendust omab siis, kui scripti sees on vaja teha nägu justkui oleks sisestus tulnud klaviatuurilt. 
<<\str
#!/bin/sh 

a=5; 

tr "[a-z]" "[A-Z]" <<\mark 
tere kas see on korras? 
ja mida muutuja $a teeb? 
mark 
 

sama asi, ainult muutujate väärtusi ei kanta üle.