Soubory, adresáře, a příkazová řádka do hloubky
Dnes si povíme, jak fungují systémy založené na
UNIXu, jako Linux a OS X.
Windows fungují podobně, takže se tyhle znalosti
budou hodit všem.
Uvítám „překlad” tohoto textu, aby byl
pochopitelnější pro uživatelky Windows – teď jsou
instrukce pro Windows v takovýchto poznámkách.
Soubory a adresáře
UNIX je založený na souborech
(angl. file)
a procesech (angl. process).
Zjednoušeně řečeno, soubor je něco z čeho se dají
číst informace nebo je tam zapisovat;
proces je program který právě běží – a může
s informacemi manipulovat.
Soubory jsou uspořádané v adresářích
(angl. directory).
Adresář je zvláštní typ souboru,
který může obsahovat další soubory (a adresáře).
Každý soubor a každý adresář tak někam „patří”.
Existuje takzvaný kořenový adresář
(angl. root directory), označovaný
lomítkem (/
),
který (nepřímo) obsahuje všechny soubory v systému.
Máš-li unixový systém, můžeš se podívat,
co obsahuje:
$ ls /
bin data etc lib lost+found mnt proc run srv tmp var
boot dev home lib64 media opt root sbin sys usr
Neboli: na příkazové řádce, za výzvu $
,
napiš příkaz ls
(vypiš adresář),
mezeru a /
(jméno adresáře, který
chceš vypsat), a stiskni Enter.
Vypíše se seznam adresářů, které v /
jsou. U tebe může seznam být trošku jiný.
Na Windows je situace jiná: neexistuje jeden
adresář, ve kterém je všechno; místo toho
má každý disk svůj kořenový adresář, jako
C:
, D:
, E:
,
atd.
Obsah můžeš vypsat příkazem dir C:\
.
Cesty
Většina ze toho, co vypsal příkaz ls /
jsou adresáře, kteŕ obsahují součásti a nastavení
systému – třeba v bin
jsou programy,
které se dají spustit, v etc
je
nastavení, proc
obsahuje informace
o běžících procesech, v tmp
jsou dočasné soubory, home
obsahuje domovské adresáře uživatelů.
Chceme-li se podívat, co obsahuje některý z těchto
adresářů, dáme před jeho jméno lomítko,
a použijeme opět příkaz ls
.
Třeba na alenčině notebooku
obsahuje adresář /home
jen jediný soubor – podadresář alenka
:
$ ls /home
alenka
Na Windows musíš dát před jméno adresáře
celé jméno disku, oddělené zpětným lomítkem. Třeba
dir C:\Documents and Settings
.
Pokud budu chtít pojmenovat adresář
alenka
, abych ho mohla vypsat pomocí
ls
,
použiju jeho umístění
(adresář, který ho obsahuje, také zvaný
rodičovský adresář,
angl. parent directory – v našem případě
/home
),
a oddělím ho lomítkem od jména samotného adresáře:
$ ls /home/alenka
Desktop Documents Downloads Music Pictures pyladies
Public Templates Videos
A stejně pro jakýkoliv jiný adresář:
$ ls /home/alenka/pyladies
01 02 03 04 05 venv
$ ls /home/alenka/pyladies/02
ahoj.py ctverec.py if.py printing.py rady.py
Na Windows to funguje stejně, jen se adresáře
oddělují zpětným lomítkem.
Takové lomítky oddělené jméno adresáře
se nazývá cesta (angl. path),
a slouží
Cesta může vést i k normálnímu souboru.
Příkaz ls
tu vypíše jméno souboru,
ne jeho obsah:
$ ls /home/alenka/pyladies/02/ahoj.py
/home/alenka/pyladies/02/ahoj.py
Pro vypsání obsahu by se místo příkazu
ls
použil cat
,
ve Windows pak místo dir
příkaz type
.
Použít normální soubor jako rodičovský adresář
nejde: cesta jako
/home/alenka/pyladies/02/ahoj.py/neco
nikam nevede.
Relativní cesty
Zatím jsme používaly cesty, které začínají lomítkem
(nebo, na Windows, jménem disku).
Co se stane, když lomítkem nezačneme?
Každá příkazová řádka má aktuální adresář
(angl. current working directory),
který se – jak jsme si ukázaly na prvním srazu – dá
vypsat příkazem pwd
a změnit příkazem cd
.
(Na Windows se příkazem cd
i vypisuje.)
Pokud zadám cestu bez počátečního lomítka,
tak místo v kořenovém adresáři
/
taková cesta začíná tak,
kde „právě jsem”.
Je to cesta relativní
(angl. relative)
vzhledem k aktuálnímu adresáři.
$ pwd
/home/alenka
$ ls /home/alenka/pyladies/02
ahoj.py ctverec.py if.py printing.py rady.py
$ ls pyladies/02
ahoj.py ctverec.py if.py printing.py rady.py
Cestám, které začínají lomítkem (či jménem disku),
se říká absolutní
(angl. absolute).
Tohle platí i ve Windows.
Pokud začíná jméno cesty jménem disku,
jde o absolutní cestu na daném disku.
Když začíná zpětným lomítkem (bez jména
disku), rozumí se aktuální disk;
Rodičovský adresář
V každém adresáři existují dva speciální adresáře:
rodičovský adresář, který se označuje dvěma
tečkami (..
),
a adresář, který se označuje jednou tečkou
(.
):
$ pwd
/home/alenka
$ ls .
Desktop Documents Downloads Music Pictures pyladies
Public Templates Videos
$ ls ..
alenka
Tyto adresáře se dají používat v cestách;
například, pokud jsem v adresáři
/home/alenka
,
tak cesta
../alenka/.
znamená:
..
: nahoru do /home
,
alenka
: zpátky do /home/alenka
,
.
: zůstat v /home/alenka
.
Jde tedy o ten samý adresář.
Ve Windows ..
a .
znamenají přesně to samé jako v Unixu,
jen se jména adresářů oddělují zpětnými lomítky.
Příkazy
A co je vlastně ono ls
,
kterým vypisujeme obsah adresáře?
Příkaz ls
je program: speciální
soubor, který se dá spustit, čímž vznikne proces
který se tím programem řídí.
Absolutní cesta k němu je /bin/ls
.
Jako programy v Pythonu, i /bin/ls
obsahuje příkazu pro počítač, které se
provádějí jeden po druhém.
(Na rozdíl od Pythonu tyto příkazy nejsou
čitelné – jsou v jazyce, kterému rozumí jen počítač.
Máš-li Linux, otevři si /bin/ls
v editoru a přesvědč se sama.)
Když zadáme do příkazové řádky ls
,
najde se soubor ls
v adresáři
/bin
, a spustí se (vytvoří se z něj
proces).
Případné argumenty (např. pokud zadáme
ls /bin
, tak bin
)
se „předají” novému procesu,
aby s nimi mohl pracovat.
Na Windows je situace trošku jiná, příkaz
dir
není uložen ve zvláštním souboru.
Ale například Poznámkový blok (Notepad) funguje
stejně – příslušný soubor bývá v
C:\Windows\System32\notepad.exe
,
a spouští se zadáním notepad
.
Proměnné
A jak příkazová řádka ví, že se příkazy mají hledat
zrovna v /bin
?
Existuje na to proměnná – ano, i příkazová řádka
má proměnné, i když fungují trochu jinak než
v Pythonu.
Dají se nastavit rovnítkem (pozor, kolem rovnítka
tu nesmí být mezery), a vypsat příkazem
echo
, kde proměnnou uvedeme
s dolarem na začátku:
$ promenna=xyz
$ echo $promenna
xyz
Na Windows zkus pro nastavení set promenna=xyz
a pro vypsání echo %promenna%
.
Proměnnou s dolarem můžeme použít v kterémkoli
příkazu; nahradí se obsahem proměnné.
Můžeme tedy napsat třeba:
$ adresar=/home/alenka/pyladies
$ echo $adresar
/home/alenka/pyladies
$ ls $adresar
Desktop Documents Downloads Music Pictures pyladies
Public Templates Videos
nebo dokonce:
$ adresar=/home/alenka/pyladies
$ prikaz=ls
$ $prikaz $adresar
Desktop Documents Downloads Music Pictures pyladies
Public Templates Videos
$PATH
Proměnná PATH
obsahuje
všechny cesty, ve kterých se mají hledat příkazy.
Jsou oddělené dvojtečkou:
$ echo $PATH
/usr/local/bin:/usr/bin:/bin:/usr/games:/usr/local/sbin:/usr/sbin:/home/petr/.local/bin:/home/petr/bin
Příkazová řádka zkouší všechny tyto adresáře,
jeden po druhém, dokud nenajde zadaný příkaz
– a první který najde, spustí.
Naše PATH
obsahuje i /bin
,
takže se najde příkaz /bin/ls
.
Na Windows je proměnná PATH
,
která funguje stejně – zkus
echo %PATH%
.
Když proměnnou PATH
změníme,
příkazová řádka začne hledat příkazy jinde –
a nemusí je vůbec najít!
$ PATH=/nejaka/neexistujici/cesta
$ ls
bash: ls: command not found...
Na Windows jde PATH
nastavit pomocí
set PATH=xyz
, ale protože je tu
víc příkazů zabudovaných (ne v souborech),
„nerozbije se to” tak moc, jako v Unixu.
Pořád se ale dá zadat absolutní cesta k příkazu:
$ /bin/ls
Desktop Documents Downloads Music Pictures pyladies
Public Templates Videos
Nebo se dá zadat i cesta relativní.
Pokud jsme v adresáři
/home/alenka
a chceme soubor
/bin/ls
, chceme
jít po této cestě:
..
– nahoru do /home
..
– nahoru do /
bin
– do /bin
ls
– k /bin/ls
$ ../../bin/ls
Desktop Documents Downloads Music Pictures pyladies
Public Templates Videos
A nebo se můžeme přepnout do adresáře /bin
,
a spustit ls
z aktuálního adresáře.
Aktuální adresář ale musíme pojmenovat přímo,
pomocí .
, jinak se příkaz hledal
v $PATH
.
$ cd /bin
$ ./ls
Desktop Documents Downloads Music Pictures pyladies
Public Templates Videos
Po tomhle experimentu je dobré si otevřít novou
příkazovou řádku, ve které bude PATH
nastaveno správně.
Virtuální prostředí
A teď už víme dost na to, abychom si vysvětlily,
jak funguje virtuální prostředí.
Virtuální prostředí je adresář – to naše prostředí
je adresář pojmenovaný venv
).
V tomto adresáři je soubor s programem
python
, který se dá spustit,
a spousta dalších souborů, které jsou pro fungování
Pythonu potřeba.
Zkus si program python
ve svém
virtuálním prostředí najít!
python
z virtuálního
prostředí ale není na žádné z cest, které
jsou normálně v PATH
,
takže se normálně nespouští – když do
čerstvě puštěné příkazové řádky napíšu
python
, spustí se
systémový Python – /usr/bin/python
– ne ten
z virtuálního prostředí.
Na většině dnešních unixových systémů má
/usr/bin/python
verzi 2.6 nebo 2.7, což se nám nehodí.
Ve virtuálním prostředí je ještě jeden program,
nazvaný activate
.
Na Unixových systémech to není samostatný program,
ale tzv. skript pro program source
–
podobně jako program v Pythonu se nespouští přímo,
ale např. python mujprogram.py
.
Virtuální prostředí se aktivuje příkazem
source ~/pyladies/venv/bin/activate
.
Je možné zadat i relativní cestu od aktuálního adresáře – to může být rychlejší,
pokud „jsme” ve správném adresáři.
Tento příkaz activate
nastaví $PATH
(a jiné proměnné) tak, aby se odteď po zadání
python
spouštěl onen Python z virtuálního prostředí.
Jedna z dalších proměnných, které activate
nastaví, se jmenuje PS1
a obsahuje
výzvu příkazové řádky (která většinou končí
$
; na Windows >
).
activate
na začátek přilepí řetězec
(venv)
, takže jednoduše poznáme,
že jsme v našem virtuálním prostředí.
$ python --version
Python 2.7.8
$ source /home/alenka/pyladies/venv/bin/activate
(venv)$ python --version
Python 3.4.0
(venv)$
Na Windows jsme „systémový” Python nainstalovaly my,
takže i ten má verzi 3.4, jak potřebujeme – jen tu
ani ten systémový není standardně v PATH
.
Pokud sis nastavila PATH
tak, aby náš
Python obsahovala (což některé
z vás udělaly), nebylo doteď až tak úplně potřeba
virtuální prostředí spouštět.
To se ale ode dneška změní, protože si začneme
„naše” prostředí měni doinstalováváním dalších
balíčků. Dávej tedy pozor, abys virtuální prostředí
měla zapnuté, když je potřeba.
Bonus: Tilda
Unixové příkazové řádky mají ještě jeden
způsob, jak zkrátit zápis:
pokud cesta začíná vlnovkou (~
),
dosadí se za vlnovku domovský adresář aktuálního
uživatele.
Lze tedy psát:
$ ls ~/pyladies/02
ahoj.py ctverec.py if.py printing.py rady.py
Pokud tedy máš adresář pyladies
přímo v domovském adresáři, tak
~/pyladies
je absolutní cesta k němu – jen zkráceně zapsaná.
Funguje to ale jen v příkazové řádce.
Až budeme se soubory pracovat z Pythonu,
~
se takhle chovat nebude –
musíme zavolat speciální funkci,
která vlnovku „rozbalí”.
$ python
>>> from os.path import expanduser
>>> print(expanduser('~/pyladies'))
/home/alenka/pyladies