Sanırım bu serinin 3. sorusu olabilir. Merak edenler önceki başlıklara bakabilirler.
https://forum.ubuntu-tr.net/index.php?topic=27239
https://forum.ubuntu-tr.net/index.php?topic=51052.0
Sorunun çözümünü
C,
C++ Rust veya
D ile yazabilirsiniz.
Soru şu: Bir klasör içinde /eski ve /yeni isminde dizinlerimiz var. /eski dizininde *.d uzantılı kaynak dosyalarımız var. Başka uzantılı dosyalar da olabilir.
/eski dizinindeki sadece değiştirilmiş *.d dosyalarını /yeni dizinine kopyalamak istiyoruz.
Örneğin ilk durumda /eski dizininin içeriği şu şekilde olsun.
Alıntı Yap$ ls -l
-rw-rw-r-- 1 erdem erdem 193 Oca 18 23:08 bir.d
-rw-rw-r-- 1 erdem erdem 64 Oca 18 23:07 uc.d
-rw-rw-r-- 1 erdem erdem 49 Oca 18 22:53 iki.d
-rw-rw-r-- 1 erdem erdem 2 Oca 19 08:53 deneme.txt
Bu durumda program hiç bir şey yapmıyor. Bir metin düzenleyici ile bir.d ve uc.d kütüğünde değişiklik yaptık. Bu iki kaynak dosyasını /yeni dizinine kopyalamasını istiyoruz.
Ayrıca üzerinde değişiklik yaptığımız ve /yeni dizinine kopyaladığımız kaynak dosyalarının çetelesini de tutmak istiyoruz. Bu nedenle programımız değişiklik olan kaynak dosyalarının bir listesini örneğin degisenler.txt isminde bir kütükte tutsun istiyoruz.
// degisenler.txt Alıntı Yapeski/bir.d
eski/uc.d
Henüz kimse yanıt yazmamış. Ama ben D ile bu örneği kodladım 8)
Merak edenler bakabilir ;)
http://ddili.org/forum/post/12475
Güzel bir soru olmuş. Kod olarak yazmadım ama aklıma ilk gelen bir template dosyası oluşturup sonra onun üzerinden kontrolünü yapmak oldu. Senin kodunu da baktım okunabilir bir kod olmuş ama d dilini pek bilmiyorum. Yorum satırları ile desteklersen kodunu daha güzel olur benim gibi bilmeyenler için :)
Açıkcası c/c++ ilgilimi kaybediyorum gerek işimden gerek rubynin beni fazla cezbetmesinden dolayı :) Fakat burada yaptığın bu güzel etkinliğin bir benzerini ruby içinde ben yapmayı düşünüyorum. Biraz daha ustalaşayım da :D
Programı anlatmak için D'nin UCFS denilen denk işlev çağırma biçimini anlamak gerekiyor.
import std.stdio;
void pişir(string isim)
{
writeln(isim ~ " pişiriyorum");
}
void main()
{
pişir("çorba");
("çay").pişir; /+ parantezleri yazmadım dikkat ederseniz +/
("ekmek").pişir;
}
Örneğin bu ilk işlevi birinci şekilde C, C++'ya benzer şekilde yazabileceğimiz gibi daha esnek bir biçimde kullanabiliyoruz.
import std.stdio;
import std.path;
import std.algorithm;
import std.file;
void main()
{
("eski/")
.dirEntries(SpanMode.depth)
.filter!(kütük => kütük.extension == ".d")
.each!writeln;
}
Bizim programın özü de bu. eski/ dizindeki DFS arama algoritması ile kütükleri listeliyor. Sonra .filter ile d uzantılıları seçiyor. each! ile herbirini yazıyor. Bunu denemek için örneğin .filter!'la başlayan satırı silerek görebilirsiniz.
import std.stdio: writeln, writefln;
import std.file: getTimes;
import std.algorithm: filter, map, each;
import std.path: dirEntries, SpanMode, extension;
import std.datetime: SysTime, DateTime;
import std.typecons: tuple;
SysTime sonDeğişiklikZamanı(string kütükİsmi)
{
SysTime sonErişimZamanı;
SysTime sonDeğişiklikZamanı;
kütükİsmi.getTimes(sonErişimZamanı, sonDeğişiklikZamanı);
return sonDeğişiklikZamanı;
}
void main()
{
const arananZaman = SysTime(DateTime(2017, 1, 22));
("eski/")
.dirEntries(SpanMode.shallow)
.filter!(isim => isim.extension == ".d")
.map!(isim => tuple(isim, isim.sonDeğişiklikZamanı))
.filter!(çokuzlu => çokuzlu[1] > arananZaman)
.each!writeln;
}
Programı daha da geliştirirsek burada sonDeğişiklikZamanı işlevi basitçe bir kütüğün en son değiştiği zamanı veriyor. Burada örneğin 22 Ocak'tan sonra değişen dosyaları süzüyoruz.
Genel olarak bu konu D'nin ileri düzey olanaklarından faydalanıyor. Merak edenler buradan okuyabilirler.
http://ddili.org/ders/d/araliklar.html
http://ddili.org/ders/d/araliklar_baska.html
Bilgilendirme için teşekkürler adaş :)
Sistem programlama yapıp rust'u dahil etmemek ayıp olur :D
Idiomatic olmayan fonksiyonel rust sürümü:
use std::fs::{File, read_dir, remove_file, hard_link};
use std::io::Write;
use std::path::Path;
fn main() {
// değişikliklerin kaydedileceği kütük dosyası
let mut kutuk = File::create("degisiklikler.txt").unwrap();
// eski dizini okunur
for degisen in read_dir("./eski").unwrap()
// dosya uzantısı "d" olan dosyalar filtrelenir
.filter(|de| de.as_ref().map(|de| de.path().extension().unwrap() == "d").unwrap())
.filter_map(|de| {
// yeni dizinindeki dosyanın yolu
let p = Path::new("./yeni").join(de.as_ref().unwrap().path().file_name().unwrap());
// eski dizinde okunan dosya yeni dizinde yoksa veya değiştirilme zamanı değişikse
if !p.exists() ||
p.metadata().unwrap().modified().unwrap() !=
de.as_ref().unwrap().metadata().unwrap().modified().unwrap() {
remove_file(&p).ok();
// yeni dizine hard_link olarak kopyalanır (değiştirilme zamanıyla birlikte)
hard_link(de.as_ref().unwrap().path(), p).unwrap();
Some(de.as_ref().unwrap().path())
} else {
None
}
}) {
// degisen dosyanın yolu kütüğe yazılır
writeln!(kutuk, "{}", degisen.to_str().unwrap()).unwrap();
println!("Değişen dosya: {:?} kopyalandı", degisen);
}
}
Idomatic olan dekleratif rust sürümü:
use std::fs::{File, read_dir, hard_link, remove_file};
use std::io::{Write, Error, ErrorKind};
use std::path::Path;
fn erdemin_d_dosyalarini_kopyala<P: AsRef<Path>>(eski: P, yeni: P) -> Result<(), Error> {
// değişikliklerin kaydedileceği kütük dosyası
let mut kutuk = try!(File::create("degisiklikler.txt"));
for de in try!(read_dir(eski.as_ref())) {
let de = try!(de);
// dosya uzantısı "d" olmayan dosyalar geçilir
if try!(de.path().extension().ok_or(Error::from(ErrorKind::Other))) != "d" {
continue;
}
// yeni dizinindeki dosyanın yolu
let p = Path::new(yeni.as_ref())
.join(try!(de.path().file_name().ok_or(Error::from(ErrorKind::Other))));
// eski dizinde okunan dosya yeni dizinde yoksa veya değiştirilme zamanı değişikse
if !p.exists() ||
try!(p.metadata().and_then(|p| p.modified())) !=
try!(de.metadata().and_then(|p| p.modified())) {
let _ = remove_file(&p);
// yeni dizine hard linklenir (değiştirilme zamanıyla birlikte vs kopyalanır)
try!(hard_link(de.path(), p));
// degisen dosyanın yolu kütüğe yazılır
let degisen =
try!(de.path().to_str().map(|s| s.to_owned()).ok_or(Error::from(ErrorKind::Other)));
try!(writeln!(kutuk, "{}", degisen));
println!("Değişen dosya: {:?} kopyalandı", degisen);
}
}
Ok(())
}
fn main() {
erdemin_d_dosyalarini_kopyala("./eski", "./yeni").expect("IO hatası");
}
Alıntı yapılan: ShangriLa - 23 Ocak 2017 - 14:19:44
Sistem programlama yapıp rust'u dahil etmemek ayıp olur :D
Idiomatic olmayan fonksiyonel rust sürümü:
[...]
Teşekkürler! :)
Bu programı denedim.
$ rustc deneme.rs
$ ./deneme
Değişen dosya: "./eski/iki.d" kopyalandı
Değişen dosya: "./eski/deneme.d" kopyalandı
Değişen dosya: "./eski/bir.d" kopyalandı
Ama ilk seferde tüm dosyaları kopyalamaması gerekiyordu ;)
Benim program değiştirilme zamanına baktığı için sizin daha önce yeni dizinine kopyalanmış olan dosyaların kopyalama methodu farklı olmuş olacağından ilk defada bunu düzeltmek için kopyalama yapmıştır.
Örneğin "cp eski/deneme.d yeni/deneme.d" derseniz bu yeni/deneme.d nin değiştirilme zamanını şu an yapar. Bu da benim programa göre yeni/deneme.d farklı bir dosya anlamına geliyor.
Fakat "ln eski/deneme.d yeni/deneme.d" derseniz tüm dosya durumlarıyla (hard link) kopyalamış olursunuz. Program bu özellikten yararlanarak değişiklikleri algılıyor.
Aslında pratikte ilk seferinde dosyaları kopyalanmamasının daha iyi bir çözüm olduğunu düşünüyorum.
Örneğin ben bu programın biraz değişik sürümünü kullanıyorum. Bir dizinde yüzlerce kaynak dosyası var. Kopyalamadan önce make komutunu çalıştırıyor. Bu da diyelim ki sadece bir tane kaynak dosyası değişmişse kısa bir derleme yapıyor. Sonra oluşan kütüphane dosyasını da başka bir dizine kopyalıyor. Ama tüm kaynak dosyalarını derlerseniz yaklaşık yarım saat sürüyor ;)
Ben şöyle bir çözüm geliştirdim. Programı ilk çalıştırdığımızda eğer yoksa degisiklikler.txt isminde bir kütük oluşturuyor ve içine o anki saati yazıyor. Örneğin:
2017-Jan-24 22:07:05.432577
Diyelim ki eski dizinindeki deneme.d kütüğünde değişiklik yaptık. Tekrar degisiklikler.txt dosyasına kontrol zamanını ve kütük ismiyle kütüğün değiştiği saati yazıyor.
2017-Jan-24 22:09:23.5360845
eski/deneme.d: 2017-Jan-24 22:08:55.1168591
Tabi bu kütük degisenler.txt listesinde yoksa bu listeye de eklemesi gerekiyor.
eski/deneme.d
Ben de bu vesileyle Rust derleyicisini denemiş oldum ;)