Ruby po kapkách (18.) – adresáře
V minulém díle jsem rozšířili naše znalosti vstupně výstupních operací o další podrobnosti práce se soubory. Tentokrát se podíváme na to, jak v Ruby procházet adresáře. Nejdříve se ale podívejme na příklad s kopírováním souboru, kterým jsme posledně končili. Možná nejjednodušším řešením, které se poněkud podobá již probíranému porovnávání souborů, je následující kód.
f1 = File.new(ARGV[0])
f2 = File.new(ARGV[1], ‚w‘)
while buffer = f1.read(2048) do
f2.write(buffer)
end
f1.close
f2.close
Takto můžeme pomocí prográmku vytvořit jeho vlastní kopii poté, co zdrojový kód uložíme do souboru s názvem copy.rb.
~$ ruby copy.rb copy.rb copycopy.rb
Soubor, jehož název získáme jak první parametr z příkazové řádky, otevřeme pro čtení. Soubor s názvem z druhého parametru otevřeme pro změnu pro zápis. Pak ve smyčce načítáme do pomocné proměnné vždy maximálně dva kilobyty ze zdrojového souboru a výsledek zapisujeme do cílového souboru. Ve smyčce využíváme skutečnosti, že metoda read
vrací hodnotu nil
v případě, že dosáhne konce souboru. To smyčku ukončí – nil
se vyhodnotí jako false
. (Důležité je uvědomit si, že se testuje hodnota celého výrazu přiřazení, která se ale rovná pravé části výrazu. Otázka na zamyšlení: co by se stalo, kdybychom udělali překlep a místo operátoru přiřazení = použili porovnávací operátor == ?) Na konec oba soubory korektně zavřeme. Opět je třeba připomenout, že zatím nepředpokládáme a nijak neřešíme možnost vzniku chyby. K této problematice se ještě dostaneme v příštích dílech. Teď však vzhůru na adresáře.
Pro reprezentaci adresářů má Ruby vestavěnou třídu Dir
. Nová instance se vytvoří voláním metod new
s řetězcovým parametrem určujícím cestu k příslušnému adresáři. Ještě než se podíváme na specifické metody třídy Dir
, prozradíme si rovnou příjemné překvapení – Dir
je enumerable. Můžeme tedy používat již známé a pohodlné metody pro procházení kolekcí. Položkami kolekce jsou v tomto případě podadresáře a soubory obsažené v adresáři.
irb(main):001:0> d = Dir.new(‚.‘)
=> #<Dir:0x28313030>
irb(main):002:0> d.to_a.join(‚, ‚)
=> „., .., .links, .xinitrc, .mc, .Xauthority, .vnc, .fontconfig, .inputrc, .gkrellm2, .profile, tmp, .bash_history, .ssh, .bashrc, .gem, copy.rb“
irb(main):003:0> d.grep(/copy/).join(‚, ‚)
=> „copy.rb“
Aniž bychom vytvářeli instanci adresáře, můžeme jím procházet pomocí indexovacího operátoru aplikovaného přímo na třídu Dir
(Vzpoměňte si, že indexovací operátor je vlastně metoda jako každá jiná, takže v tomto případě metoda třídy Dir
). Indexem může být výraz, který má podobná pravidla jako expanzní znaky v shellu: * nahrazuje libovolný řetězec, ? nahrazuje jeden libovolný znak. Navíc je možné použít třídu znaků v hranatých závorkách. Specialitou je použití kombinace **, která odpovídá rekurzivně podadresářům. Lze tak projít celou adresářovou strukturu. Výsledkem je pole nalezených názvů.
irb(main):004:0> Dir[‚*.rb‘]
=> [„copy.rb“]
irb(main):005:0> Dir[‚**/*.rb‘].size
=> 86
Mezi metodami třídy Dir
jsou dále zajímavé ty, které umožňují běžnou manipulaci s adresáři. Názvy metod jsou podobné jako odpovídající unixové příkazy. Následující relace irb
ukazuje vytvoření podadresáře, přepnutí aktuálního adresáře na nově vytvořený podadresář, návrat zpět a vymazání podadresáře.
irb(main):001:0> Dir.mkdir(‚test‘)
=> 0
irb(main):002:0> Dir.chdir(‚test‘)
=> 0
irb(main):003:0> Dir.pwd
=> „/home/dali/test“
irb(main):004:0> Dir.chdir(‚..‘)
=> 0
irb(main):005:0> Dir.rmdir(‚test‘)
=> 0
Když už jsem u těch metod s názvy podobnými unixovým příkazům, nedá mi zmínit velmi silnou metodu test
, která dělá totéž, co stejnojmenný unixový příkaz – testuje platnost různých předpokladů o souborech nebo o nich zjišťuje informace. Metoda patří přímo třídě Object
a můžeme ji tedy volat bez příjemce (úplně přesně řečeno je metoda definována v modulu Kernel
, který je do třídy Object
namixován). Následující relace zjistí popořadě čas přístupu, změny a modifikace (tak, jak byly definovány v minulém díle) a vrátí je jako instanci třídy Time
. Pak zjišťuje, zda se v několika případech jedná o adresář nebo standardní soubor.
irb(main):001:0> test ?A, ‚copy.rb‘
=> Thu Jul 23 19:50:01 +0200 2009
irb(main):002:0> test ?C, ‚copy.rb‘
=> Thu Jul 23 22:40:34 +0200 2009
irb(main):003:0> test ?M, ‚copy.rb‘
=> Thu Jul 23 19:49:43 +0200 2009
irb(main):004:0> test ?d, ‚copy.rb‘
=> false
irb(main):005:0> test ?d, ‚tmp‘
=> true
irb(main):006:0> test ?f, ‚copy.rb‘
=> true
irb(main):007:0> test ?f, ‚tmp‘
=> false
irb(main):008:0> test ?f, ‚xxx‘
=> false
Povšimněte si, že prvním parametrem, který určuje druh testu, je ve skutečnosti integer. Otazník se znakem je v tomto případě speciálním literálem, který vrací kód znaku. Mnemotechnicky pak parametry odpovídají ASCII kódům znaků, které nějak souvisí s testem (?d – jedná se o adresář – directory, ?f – jedná se o soubor – file). Podrobnější výpis všech dostupných testů poskytne jako obvykle referenční příručka na http://www.ruby-doc.org/. Poněkud více objektově orientovaně se ke všem funkcionalitám, které nabízí metoda test
, dostaneme pomocí volání metody třídy File.stat
. Tato metoda vrací instanci třídy File::Stat
, která zapouzdřuje metainformace o souboru a nabízí různé metody, kterými lze zjišťovat konkrétní vlastnosti. Názvy metod jsou samovysvětlující, jak je vidět z následující ukázky.
irb(main):010:0> t = File.stat(‚copy.rb‘)
=> #<File::Stat dev=0x68, ino=8435247, mode=0100644, nlink=1, uid=1001, gid=1001, rdev=0x2029a07, size=131, blksize=4096, blocks=4, atime=Thu Jul 23 19:50:01 +0200 2009, mtime=Thu Jul 23 19:49:43 +0200 2009, ctime=Thu Jul 23 22:40:34 +0200 2009>
irb(main):011:0> t.file?
=> true
irb(main):012:0> t.ftype
=> „file“
irb(main):013:0> t.size
=> 131
irb(main):014:0> t.readable?
=> true
Nyní máme dostatek informací (snad kromě toho, že jsme minule explicitně neuvedli, že metoda File.rename
kromě přejmenování umí i přesouvat soubory z jednoho adresáře do druhého), abychom mohli vyřešit zajímavou a malinko složitější úlohu z praxe. Vystupuje v ní IP kamera, která přes FTP nahrává do daného adresáře snímky. Snímky se ukládají do souborů s názvem, který odpovídá vzorci n.jpg, kde n je unikátní číslo. V adresáři tak vzniká obrovské množství souborů, se kterými se obtížně pracuje. Úkolem je vytvořit program, který po spuštění přesune všechny obrázky, které jsou starší než z aktuálního dne, do podadresářů, přičemž pro každý den v minulosti, pro který existují obrázky, vytvoří podadresář (pokud již neexistuje). Podadresář se bude jmenovat podle vzorce RRMMDD – písmena podchopitelně kódují příslušný rok, měsíc a den. Program bude spouštěn s parametrem určujícím cestu do adresáře s obrázky. Vzorové řešení uvedeme opět v příštím díle.
Mohlo by vás také zajímat
-
Lék na phishing a apatii ve světě e-mailového marketingu
18. března 2024 -
Chcete jedinečnou doménu? Objevte koncovky FOOD, MEME a MUSIC!
7. listopadu 2024 -
inPage AI: Jak na generování obsahu
18. července 2024
Nejnovější
-
Výkonný a kompaktní: ASOME Max Studio s výjimečným poměrem cena/výkon
11. listopadu 2024 -
Šokující data od Microsoftu: Kyberútoky rostou o stovky procent!
8. listopadu 2024 -
Chcete jedinečnou doménu? Objevte koncovky FOOD, MEME a MUSIC!
7. listopadu 2024 -
OpenAI představilo novou funkci ChatGPT Search
6. listopadu 2024