Naprej Nazaj Vsebina

3. Relativno osnovna vprašanja, ki jih navadno sprašujejo začetniki

3.1 Kako odstranim datoteko z imenom, ki se začne z ,-`?

Subject: How do I remove a file whose name begins with a "-" ?
Date: Thu Mar 18 17:16:55 EST 1993
Poiščite tak način imenovanja datoteke, da se ne začne s pomišljajem. Najpreprostejši odgovor je primer
rm ./-imedatoteke
(seveda predvidevamo, da je ,,-imedatoteke`` v tem primeru v trenutnem imeniku).

Ta način izogibanja dvoumnemu ,-` na začetku imen deluje tudi pri drugih ukazih.

Veliko ukazov, posebej tistih, ki so bili napisani z uporabo rutine ,,getopt(3)`` za razčlembo argumentov, sprejme tudi argument ,,--``, ki pomeni ,,to je zadnja izbira, vse po tem ni več izbira``. Vaša različica rm potemtakem morebiti razume tudi

rm -- -imedatoteke
Nekatere različice rm, ki ne uporabljajo getopt(), razumejo podobno tudi en sam ,,-``, torej lahko poskusite kar z ,,rm - -imedatoteke``.

3.2 Kako odstranim datoteko, ki ima v svojem imenu čudne znake?

Subject: How do I remove a file with funny characters in the filename ?
Date: Thu Mar 18 17:16:55 EST 1993
Če je ,,čuden znak`` znak ,/`, preskočite na zadnji del odgovora. Če je čuden znak nekaj drugega, na primer presledek ali kontrolni znak ali znak s prižganim osmim bitom (to so npr. slovenske črke ,,蚞ȊŽ``), nadaljujte z branjem.

Prvi klasični odgovor je uporaba ukaza na način

rm -i vzorec*ki*ustreza*le*datoteki*ki*jo*želite
Ukaz vpraša za vsako datoteko, ki ustreza vzorcu, če jo želite odstraniti. Nasvet morda v vaši ukazni lupini ne bo deloval zaradi znakov s prižganim osmim bitom, saj ga ukazna lupina lahko odreže.

Drugi klasični odgovor je

rm -ri .
ki vas za vsako datoteko v trenutnem imeniku vpraša, ali naj jo odstrani.

V angleškem okolju odgovorite z ,y` pri problematični datoteki in z ,n` pri vseh ostalih datotekah. Žal to ne deluje pri veliko različicah rm. Hkrati se bo ukaz izvedel za vse datoteke na vseh podimenikih trenutnega imenika, torej boste morda začasno hoteli te imenike narediti nedostopne z ,,chmod a-x``, da vas ne bodo motili.

Vselej globoko vdihnite in razmislite, kaj počnete, ter dvakrat preverite, kaj ste zapisali v ukazni vrstici, kadar uporabljate zastavico ,,-r`` ukaza rm ali znaka * ali ? (angl. wildcard).

Tretji klasični odgovor je

find . -type f ... -ok rm '{}' \;
kjer je ,,...`` skupina oznak, ki enolično določa ime datoteke. Ena od možnosti je, da za problematično datoteko poiščete njeno številko inode (z uporabo ukaza ,,ls -i .``) in potem uporabite
find . -inum 12345 -ok rm '{}' \;
ali
find . -inum 12345 -ok mv '{}' novo-ime-datoteke \;
,,-ok`` je varnostno preverjanje - program vas bo vprašal za potrditev ukaza, preden ga bo izvedel. Spraševanju se lahko izognete z uporabo ,,-exec``, če radi živite nevarno, ali če domnevate, da ime datoteke vsebuje zaporedje čudnih znakov, ki vam bodo ob izpisu zmešali zaslon.

Kaj, če ime datoteke vsebuje znak ,/`?

Te datoteke so res posebni primeri in jih lahko ustvari le hroščata koda v jedru (tipično jih naredijo implementacije NFS, ki ne počistijo neveljavnih znakov iz imen datotek na oddaljenih strojih). Najprej poskušajte natanko razumeti, zakaj je ta problem tako izjemen.

Spomnite se, da so imeniki v Unixu preprosto pari imen datotek in številk inode. Imenik tipično vsebuje podobno informacijo:

ime datoteke  inode

datoteka1     12345
datoteka2.c   12349
datoteka3     12347

Teoretično sta ,/` in ,\0` le dva znaka, ki se ne moreta pojaviti v imenu datoteke - znak ,/` zato, ker se uporablja za ločevanje imenikov in datotek, in znak ,\0` zato, ker končuje ime datoteke.

Žal nekatere izvedbe omrežnega datotečnega sistema NFS prešerno ustvarjajo datoteke z vključenimi nagibnicami kot odgovor na zahteve oddaljenih strojev. Na primer, to se lahko zgodi, ko se nekdo na Macu ali drugem ne-Unixu odloči narediti oddaljeno datoteko NFS na vašem Unixu, z datumom v imenu datoteke. Vaš imenik na Unixu ima potem v sebi tole:

ime datoteke  inode

91/02/07      12357
Takšne datoteke ne bo pobrisalo nobeno zgoraj opisano čaranje z ukazoma find in rm, saj morata tako tadva pripomočka kot tudi vsi drugi programi na Unixu razumeti znak ,/` na običajen način.

Vsak običajen program bo želel narediti unlink("91/02/07"), kar jedro razume kot ,,pobriši datoteko 07 v podimeniku 02 imenika 91``, toda to ni tisto, kar hočemo - imamo datoteko imenovano ,,91/02/07`` v trenutnem imeniku. To je komaj zaznavna, a ključna razlika.

Kaj lahko naredite v tem primeru? Najprej se poskusite vrniti na Maca, ki je ustvaril ta nevšečni vnos, in skušajte prepričati Maca in vaš lokalni strežnik NFS, da datoteko preimenujeta v nekaj, kar ne vsebuje nagibnic.

Če to ne deluje ali morda ni izvedljivo, boste potrebovali pomoč vašega sistemskega upravitelja, ki bo moral poskusiti kaj od naslednjega. Uporabite ,,ls -i``, da boste izvedeli številko inode nesrečne datoteke, potem odklopite datotečni sistem (z umount), uporabite ,,clri`` za izbris inodea, in popravite datotečni sistem s ,,fsck`` in s stisnjenimi pestmi. Postopek uniči podatke o datoteki. Če jih želite obdržati, lahko poskusite:

Potem boste datoteko poiskali takole: Alternativa temu pristopu je popravljanje imenika na zahteven način z brkljanjem po surovem datotečnem sistemu (angl. raw file system). Uporabite ,,fsdb``, če ga imate.

3.3 Kako dobim rekurziven izpis vsebine imenika?

Subject: How do I get a recursive directory listing?
Date: Thu Mar 18 17:16:55 EST 1993

Nekaj od tega bo naredilo to, kar želite:

ls -R                   (vse različice ,ls` nimajo ,-R`)
find . -print           (to mora delovati povsod)
du -a .                 (pokaže ime in velikost)
Če iščete vzorec z jokerji (angl. wildcard), ki bo ustrezal vsem datotekam ,,.c`` v tem imeniku in pod njim, ga ne boste našli, pač pa lahko uporabite:
% nek-ukaz `find . -name '*.c' -print`
,,find`` je zmogljiv program. Poučite se o njem.

3.4 Kako lahko v svoj pozivnik vključim ime trenutnega imenika?

Subject: How do I get the current directory into my prompt?
Date: Thu Mar 18 17:16:55 EST 1993

Odvisno od tega, katero ukazno lupino uporabljate. V nekaterih ukaznih lupinah je to preprosto, v drugih pa težko ali celo nemogoče.

3.5 Kako s skriptom ukazne lupine preberem znake s terminala?

Subject: How do I read characters from the terminal in a shell script?
Date: Thu Mar 18 17:16:55 EST 1993

V sh, uporabite read. Navadno se uporabi podobna zanka:

while read vrstica
do
    echo $vrstica
    ...
done

V csh uporabite $<, kot tukaj:

while ( 1 )
    set vrstica = "$<"
    if ( "$vrstica" == "" ) break
    ...
end
Žal se v csh ne da razločevati med prazno vrstico in koncem datoteke.

Če uporabljate sh in bi radi prebrali en sam znak s terminala, lahko poskusite nekaj podobnega:

echo -n "Vstavite znak: "
stty cbreak         # ali  stty raw
beriznak=`dd if=/dev/tty bs=1 count=1 2>/dev/null`
stty -cbreak

echo
echo "Hvala, da ste vtipkali $beriznak ."

3.6 Kako preimenujem *.foo v *.bar ali spremenim imena datotek v male črke?

Subject: How do I rename "*.foo" to "*.bar", or change file names to lowercase?
Date: Thu Mar 18 17:16:55 EST 1993

Zakaj ne deluje ,,mv *.foo *.bar``? Premislite, kako ukazna lupina razvija jokerje (angl. wildcards). Niza ,,*.foo`` in ,*.bar`` se razvijeta, preden ukaz mv sploh vidi argumente. Odvisno od vaše ukazne lupine lahko to spodleti na več načinov. CSH izpiše ,,No match.``, ker ne najde ,,*.bar``. SH izvede ,,mv a.foo b.foo c.foo *.bar``, kar bo uspelo le, če imate en sam imenik, ki ustreza ,,*.bar``, kar je zelo neverjetno in skoraj zagotovo ni tisto, kar ste imeli v mislih.

Odvisno od vaše ukazne lupine lahko to storite z zanko, v kateri poženete ,,mv`` na vsaki posamezni datoteki. Če ima vaš sistem ,,basename``, lahko uporabite:

Nekatere ukazne lupine poznajo posebne mehanizme za zamenjavo vrednosti spremenljivk (angl. variable substitution features), tako lahko namesto ukaza ,,basename`` uporabite vgrajene mehanizme, kot so: Če nimate ukaza ,,basename`` ali bi želeli preimenovati foo.* v bar.*, lahko uporabite kar ,,sed`` ali podobno orodje, da predelate ime datoteke, a v splošnem je ideja zanke enaka. S pripomočkom ,,sed`` lahko spremenite imena datotek v ukaze za mv in pošljete ukaze za izvajanje lupini ,,sh``. Poskusite:
ls -d *.foo | sed -e 's/.*/mv & &/' -e 's/foo$/bar/' | sh
Obstaja program Vladimirja Lanina, imenovan ,,mmv``, ki opravi preimenovanje datotek in je bil aprila 1990 objavljen v comp.sources.unix (Volume 21, issues 87 and 88). Omogoča vam uporabo na način
mmv '*.foo' '=1.bar'
V ukaznih lupinah zanke, podobne zgornjim, pomagajo pri zamenjavi imen datotek iz velikih črk v male ali obratno. Velike črke v imenih datotek prevedete v male takole: Če želite biti posebno temeljiti in pravilno obravnavati datoteke z izrojenimi imeni (ki vključujejo presledke ali takorekoč karkoli), boste morali uporabiti:

3.7 Zakaj dobim ob ukazu ,,rsh gostitelj ukaz`` [kakšno čudno sporočilo o napaki]?

Subject: Why do I get [some strange error message] when I "rsh host command" ?
Date: Thu Mar 18 17:16:55 EST 1993
(Govorimo o programu za oddaljeno ukazno lupino ,,rsh``, ki se ponekod imenuje ,,remsh`` ali ,,remote``. Obstaja tudi ukazna lupina z omejitvami, imenovana ,,rsh``, kar pa je druga stvar.)

Če vaš oddaljeni račun uporablja C-jevsko ukazno lupino (csh), bo oddaljeni gostitelj pognal csh, da bi izvedel vaš ,ukaz`, in ukazna lupina bo prebrala vašo oddaljeno datoteko .cshrc. Morda ta .cshrc vsebuje ,,stty``, ,,biff`` ali kakšen drug ukaz, ki ni primeren za neinteraktivno ukazno lupino. Nepričakovan izhod ali sporočilo o napaki pri teh ukazih lahko zapleteta vašo lupino rsh na čudne načine.

Tukaj je primer. Denimo, da imate v vaši datoteki .cshrc tole:

stty erase ^H
biff y
Dobili boste čudna sporočila, kot je tole:
% rsh nek-stroj date
stty: : Can't assign requested address
Where are you?
Tue Oct  1 09:24:45 EST 1991
Podobne napake lahko dobite, če izvajate določena opravila pripomočkov ,,at`` ali ,,cron``, ki prav tako bereta vašo datoteko .cshrc.

Na srečo je popravek preprost. Zelo verjetno je v vaši datoteki ,,.cshrc`` na kupe operacij, ki jih preprosto ni vredno izvajati drugje kot v interaktivnih ukaznih lupinah (npr. ,,set history=N``). Tedaj jih postavite v pogojni blok v vaši ,,.cshrc`` z

if ( $?prompt ) then
        operacije...
endif
Ker v neinteraktivnih ukaznih lupinah spremenljivka ,,prompt`` ni nastavljena, bodo sporne operacije izvedene le v interaktivnih ukaznih lupinah.

Morda boste želeli premakniti nekatere ukaze v vaš prijavni skript .login. Če se morajo ti ukazi izvesti le ob vaši prijavi na sistem (iskanje nove pošte, neprebranih novičarskih sporočil in tako naprej), jih je bolje imeti v datoteki .login.

3.8 Kako naj {nastavim spremenljivko okolja, spremenim imenik} znotraj programa ali skripta ukazne lupine in dosežem, da bo to upoštevala moja trenutna ukazna lupina?

Subject: How do I ... and have that change affect my current shell?
Date: Thu Mar 18 17:16:55 EST 1993

V splošnem tega ne morete storiti, vsaj ne brez posebnih priprav. Ko nek proces ustvari svoj podproces, ta podeduje kopijo spremenljivk svojega očeta (vključno s trenutnim imenikom). Otrok lahko spremeni podedovane vrednosti, kolikor hoče, vendar te spremembe ne bodo prizadele starševskega okolja, saj otrok spreminja le svojo kopijo originalnih podatkov.

Možne so nekatere posebne priprave. Vaš otroški proces lahko izpiše spremenjene spremenljivke, če je oče vnaprej pripravljen prebrati ta izhod in ga razumeti tako, da ustrezno nastavi svoje lastne spremenljivke.

Ukazne lupine lahko izvajajo skripte tudi v okolju osnovnega procesa, namesto v okolju podprocesa, in tedaj bodo spremembe prizadele tudi osnovno ukazno lupino.

Na primer, če je vašemu skriptu za csh ime ,,mojskript`` in ta vsebuje:

cd /zelo/dolga/pot setenv PATH /nekaj:/nekaj-drugega
ali če imate podoben skript za Bournovo ali Kornovo ukazno lupino
cd /zelo/dolga/pot PATH=/nekaj:/nekaj-drugega export PATH
in poskušate pognati ,,mojskript`` v vaši ukazni lupini, se bo vaša ukazna lupina razvejila in pognala lupinski skript kot svoj podproces, v katerem bo izvedla ukaz ,,cd``. Ta bo spremenil svoj trenutni imenik, in z ukazom ,,setenv`` spremenil svoje okolje, vendar nobeden od ukazov ne bo vplival na trenutni imenik ukazne lupine, v katerem tipkate (vaše prijavne ukazne lupine, denimo).

Če želite prepričati vašo prijavno ukazno lupino, da požene skript v trenutnem procesu (brez razvejevanja), morate uporabiti ukaz ,,.`` (za Bournovo ali Kornovo lupino) ali ukaz ,,source`` (za lupino C). Se pravi, v Bournovih ali Kornovih ukaznih lupinah napišete

. mojaskripta
v lupini C pa
source myscript

Če je vse, kar poskušate storiti, le sprememba imenika ali nastavitev spremenljivke okolja, bo verjetno najlažje, da uporabite vzdevek (angl. alias) v lupini C ali funkcijo v Bournovi/Kornovi ukazni lupini. Glejte razdelek ,,Kako lahko dobim trenutni imenik v moj pozivnik?`` za nekaj primerov.

Veliko bolj podroben odgovor je pripravil Thomas Michanek <xtm@telelogic.se>. Dobite ga lahko po FTP-ju z naslova ftp://ftp.wg.omron.co.jp/pub/unix-faq/docs/script-vs-env.

3.9 Kako lahko v csh ločeno preusmerim stdout in stderr?

Subject: How do I redirect stdout and stderr separately in csh?
From: msb@sq.com (Mark Brader)
Date: Mon, 26 Oct 1992 20:15:00 -0500

V csh lahko preusmerite stdout z ,,>`` ter hkrati stdout in stderr z ,,>&``, a ni neposrednega načina le za preusmeritev stderr. Najboljše, kar lahko naredite, je

( ukaz >datoteka_za_stdout ) >&datoteka_za_stderr
ki požene ,,ukaz`` v ukazni podlupini; stdout se preusmeri znotraj podlupine v datoteko ,,datoteka_za_stdout``, stdout in stderr podlupine pa se skupaj preusmerita v datoteko ,,datoteka_za_stderr``, toda na tej točki je stdout že preusmerjen, tako da v datoteki ,,datoteka_za_stderr`` konča pravzaprav le stderr.

Če želite le preprečiti preusmeritev stdout, tedaj to za vas stori sh:

sh -c 'ukaz 2>datoteka_za_stderr'

3.10 Kako znotraj .cshrc ugotovim, ali sem prijavna ukazna lupina?

Subject: How do I tell inside .cshrc if I'm a login shell?
Date: Thu Mar 18 17:16:55 EST 1993

Ko ljudje govorijo tako, pravzaprav s tem mislijo nekaj od naslednjega:

Morda lahko ugotovite, ali je vaša ukazna lupina resnično prijavna lupina (se pravi, bo prebrala ,,.login`` potem, ko bo opravila z ,,.cshrc``) tako, da zapravljate čas s ,,ps`` in ,,$$``. Prijavne lupine imajo v splošnem imena, ki se začnejo s ,-`. Če vas v resnici zanimata drugi dve vprašanji, je tukaj način organizacije vaše datoteke .cshrc, da to izveste.


if (! $?CSHLEVEL) then
        #
        # To je "najvišjenivojska" ukazna lupina,
        # morda prijavna lupina, morda lupina, pognana z
        # 'rsh stroj nek-ukaz'
        # Tukaj moramo nastaviti pot PATH in vse drugo,
        # kar želimo imeti v vsaki od naših ukaznih lupin.
        #
        setenv      CSHLEVEL        0
        set home = ~username        # za vsak slučaj
        source ~/.env               # nastavimo okolje
else
        #
        # Ta lupina je otrok ene od drugih ukaznih lupin, zato
        # nam ni treba ponovno nastaviti vseh spremenljivk okolja.
        #
        set tmp = $CSHLEVEL
        @ tmp++
        setenv      CSHLEVEL        $tmp
endif

# Izhod iz .cshrc, če ni interaktivna, npr. pod rsh.
if (! $?prompt) exit

# Tukaj smemo nastaviti pozivnik ali vzdevke, ki bi bili
# uporabni le za interaktivne ukazne lupine.

source ~/.aliases

3.11 Kako v lupini naredim ujemalni vzorec, ki se ujema z vsemi datotekami, razen z ,,.`` in ,,..``?

Subject: How do I construct a ... matches all files except "." and ".." ?
Date: Thu Mar 18 17:16:55 EST 1993

In vi ste mislili, da bo to preprosto ...

*

Ustreza vsem datotekam, ki se ne začenjajo z ,,.``;

.*

Ustreza vsem datotekam, ki se začenjajo z ,,.``, toda to vključuje posebna vnosa ,,.`` in ,,..``, ki ju pogosto ne želite;

.[!.]*

(Le novejše ukazne lupine; nekatere lupine uporabljajo ,,^`` namesto ,,!``; ukazne lupine POSIX-a morajo sprejeti ,,!``, a lahko sprejmejo tudi ,,^``; prenosljive aplikacije ne bi smele uporabljati necitiranega ,,^`` takoj za ,,[``.)

Ustreza vsem datotekam, ki se začnejo z ,,.`` in jim sledi ne-,,.``; žal bo to spregledalo ,,..foo``;

.??*

Ustreza datotekam, ki se začnejo z ,,.`` in so dolge vsaj tri znake. To se prikupno izogne ,,.`` in ,,..``, a tudi spregleda ,,.a``.

Če želite varno ujemanje z vsemi datotekami, razen ,,.`` in ,,..``, morate uporabiti 3 vzorce (če nimate imen datotek, kot je ,,.a``, lahko izpustite prvega):
.[!.]* .??* *
Alternativno lahko zaposlite zunanji program ali dva in uporabite substitucijo znotraj narekovaja (angl. backquote substitution). To (ali ,ls -A` na nekaterih različicah Unixa) je precej dobro:
`ls -a | sed -e '/^\.$/d' -e '/^\.\.$/d'`
a tudi to bo zamočilo pri datotekah z znaki za novo vrsto, znaki IFS ali jokerjih v njihovih imenih.

V ksh lahko uporabite:

.!(.|) *

3.12 Kako poiščem zadnji argument v skriptu Bournove ukazne lupine?

Subject: How do I find the last argument in a Bourne shell script?
Date: Thu Mar 18 17:16:55 EST 1993

Odgovor sta prispevala:

Če ste prepričani, da argumentov ni več kot devet, potem lahko uporabite:
eval zadnji=\${$#}

V ukaznih lupinah, združljivih s standardom POSIX, to deluje za vsako število argumentov. Vselej deluje tudi:

for zadnji
do
        :
done
Primer se posploši takole:
for i
do
        predpredzadnji=$predzadnji
        predzadnji=$zadnji
        zadnji=$i
done
Zdaj pa denimo, da želite odstraniti zadnji argument iz seznama ali obrniti seznam argumentov ali za vsak N dostopati neposredno do N-tega argumenta. Tukaj navajamo osnovni primer, kako to storiti, in uporabimo le vgrajene konstrukte ukazne lupine, ne da bi ustvarjali dodatne podprocese:
t0= u0= ostanek='1 2 3 4 5 6 7 8 9' argv=

for h in '' $ostanek
do
        for t in "$t0" $ostanek
        do
                for u in $u0 $ostanek
                do
                        case $# in
                        0)
                                break 3
                        esac
                        eval argv$h$t$u=\$1
                        argv="$argv \"\$argv$h$t$u\""   # (1)
                        shift
                done
                u0=0
        done
        t0=0
done

# zdaj obnovimo argumente
eval set x "$argv"                                      # (2)
shift
Ta primer deluje za prvih 999 argumentov. Dovolj? Dobro poglejte vrstici, označeni z (1) in (2) in se prepričajte, da se originalni argumenti res obnovijo, ne glede na to, katere čudne znake vsebujejo!

N-ti argument lahko zdaj poiščete takole:

eval argN=\$argv$N
Če želite obrniti argumente, morate spremeniti vrstico, označeno z (1),
argv="\"\$argv$h$t$u\" $argv"
Kako odstranite zadnji argument, vam prepuščamo za nalogo.

Če dovoljujete tudi podprocese, ki morda izvajajo nevgrajene ukaze, lahko spremenljivke ,argvN` določite preprosteje:

N=1

for i
do
        eval argv$N=\$i
        N=`expr $N + 1`
done
Za obračanje argumentov obstaja še preprostejša metoda, ki niti ne ustvarja podprocesov. Ta pristop lahko uporabite tudi, ko želite pobrisati npr. zadnji argument, a v tem primeru se ne morete več sklicevati neposredno na N-ti argument, saj so spremenljivke ,argvN` nastavljene v obratnem vrstnem redu:
argv=

for i
do
        eval argv$#=\$i
        argv="\"\$argv$#\" $argv"
        shift
done

eval set x "$argv"
shift

3.13 Kaj je narobe, če imam ,.` v svoji poti $PATH?

Subject: What's wrong with having '.' in your $PATH ?
Date: Thu Mar 18 17:16:55 EST 1993

Malce ozadja: spremenljivka okolja PATH je seznam imenikov, ločenih z dvopičji. Ko vpišete ukaz brez jasno določene poti (npr. napišete ,,ls`` in ne ,,/bin/ls``), vaša ukazna lupina išče izvedljivo datoteko s tem imenom po vseh imenikih, naštetih v seznamu PATH, lepo po vrsti, in izvede prvi program, ki ga najde.

Eden od imenikov v seznamu PATH je lahko tudi trenutni imenik ,,.``. Kot znak za trenutni imenik v seznamu PATH lahko uporabite tudi prazni imenik. Ta dva načina označevanja sta ekvivalentna:

Posestvovanje ,,.`` nekje v PATH je udobno - za poganjanje programov v trenutnem imeniku lahko namesto ,,./a.out`` napišete ,,a.out``. A obstaja kavelj.

Premislite, kaj se zgodi v primeru, da je ,,.`` prvi vnos v seznamu PATH. Denimo, da je vaš trenutni imenik javno dostopen za pisanje, na primer ,,/tmp``. Če je tam slučajno program, imenovan ,,/tmp/ls``, ki ga je tam pustil kak drug uporabnik, ter vi napišete ,,ls`` (namesto, da bi, seveda, pognali običajen program ,,/bin/ls``), bo vaša ukazna lupina pognala ,,./ls``, program tistega drugega uporabnika. Odveč je napisati, da vas lahko poganjanje neznanega programa, kot je ta, nadvse preseneti.

Bolje je postaviti oznako za trenutni imenik ,,.`` na konec PATH:

setenv PATH /usr/ucb:/bin:/usr/bin:.
Če ste zdaj v imeniku /tmp in napišete ,,ls``, bo ukazna lupina najprej preiskala /usr/ucb, /bin in /usr/bin za program, imenovan ,,ls``, preden bo pogledala v ,,.``, kar daje manj možnosti, da bi nehote pognali program ,,ls`` drugega uporabnika. Tudi to ni povsem varno - če ste neroden strojepisec in nekega dne napišete ,,sl -l`` namesto ,,ls -l``, tvegate, da boste pognali ,,./sl``, če ta obstaja. Kak ,,bister`` programer lahko računa na pogoste tipkarske napake in pušča programe s takimi imeni raztrosene po javnih imenikih. Pazite!

Veliko izkušenih uporabnikov Unixa shaja povsem dobro, ne da bi sploh imeli ,,.`` vključen v PATH:

setenv PATH /usr/ucb:/bin:/usr/bin
Če naredite to, boste morali za zagon programov vselej pisati ,,./program`` namesto program, a povečanje varnosti je verjetno vredno tega truda.

3.14 Kako lahko iz skripta ukazne lupine zapiskam na terminalu?

Subject: How do I ring the terminal bell during a shell script?
From: uwe@mpi-sb.mpg.de (Uwe Waldmann)
Date: Fri, 30 Apr 93 16:33:00 +0200

Odgovor je odvisen od različice vašega Unixa (ali raje od vrste programa ,,echo``, ki je na voljo na vašem stroju).

BSD-jevski ,,echo`` uporablja izbiro ,,-n`` za preprečitev izpisa končnega znaka za konec vrstice (angl. final newline) in ne razume osmiškega zapisa \nnn. Ukaz se torej glasi

echo -n '^G'
kjer ^G pomeni dobesedni znak BEL (vstavite ga lahko v Emacsu s kombinacijo ,,Ctrl-Q Ctrl-G`` ali v vi z uporabo ,,Ctrl-V Ctrl-G``).

Na Unixih SysV ukaz ,,echo`` razume zapis \nnn in uporablja \c za preprečitev izpisa končnega znaka za konec vrstice, torej je odgovor:

echo '\007\c'

3.15 Zakaj ne morem uporabiti programa ,,talk`` za pogovor s prijateljem na stroju X?

Subject: Why can't I use "talk" to talk with my friend on machine X?
From: tmatimar@isgtec.com (Ted Timar)
Date: Thu Mar 18 17:16:55 EST 1993
Unix ima tri razširjene programe ,,talk`` in nobeden od njih se ne zna pogovoriti z ostalima. ,,Stari`` talk vključuje prva dva tipa. Ta različica (pogosto imenovana otalk) pri pogovoru med stroji ni upoštevala vrstnega reda bytov. Zaradi tega se različica otalk za Vax ni mogla pogovarjati z različico otalk za Sun. Te različice talk-a uporabljajo vrata 517.

Okoli leta 1987 se je večina proizvajalcev (razen Suna, ki je potreboval šest let več od svojih tekmecev) dogovorila o standardu za novi program talk (pogosto imenovan ntalk), ki ve za omrežni vrstni red bytov. Ta talk deluje med vsemi stroji, ki ga podpirajo. Ta različica talk-a uporablja vrata 518.

Dandanes obstaja nekaj programov talk, ki hkrati govorijo ntalk in eno od različic otalk. Najbolj znan med njimi se imenuje ,,ytalk``.

3.16 Zakaj da koledar napačen izpis?

Subject: Why does calendar produce the wrong output?
From: tmatimar@isgtec.com (Ted Timar)
Date: Thu Sep  8 09:45:46 EDT 1994
Pogosto ljudje ugotovijo, da izhod Unixovega koledarskega programa ,,cal`` ne ustreza njihovim pričakovanjem.

Koledar za september 1752 je zelo čuden:

   September 1752
 S  M Tu  W Th  F  S
       1  2 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
To je mesec, v katerem so ZDA (pravzaprav celoten Britanski Imperij) zamenjale julijanski koledar z gregorijanskim.

Drug pogost problem, ki ga imajo ljudje s koledarskim programom, je, da mu podajajo argumente kot je ,,cal 9 94``. To izpiše koledar za september leta 94, ne pa leta 1994.


Naprej Nazaj Vsebina