Split Komutu Kullanımı

AWK ve SED komutlarıyla yaptığımız değişikliklerin ardından, yine HEAD ve TAIL komutlarını da dahil ederek yeni bir komut ile metin, dosya ve dosya içeriği işlemlerini genişletmek istiyorum.

AA

Bu vesileyle ele alacağımız komutumuz; Split ve dosyaları istediğimiz boyuttaki parçalara bölmemizi mümkün kılmakta. Komut ile ilgili detaylara geçelim.

Split Komutu ve Kullanımı

Split, Unix temelli işletim sistemlerinde dosyaları parçalara bölmemizi sağlayan, oldukça pratik bir kullanıma sahip bir komuttur. Ancak, bazı temel sınırları vardır. Örneğin, işlemi doğrudan dosya içeriğini temle alarak gerçekleştirdiği için CSV gibi dosyalarda yer alabilecek başlıkları (header) da yığının bir parçası olarak değerlendirir. Bu gibi durumlarda diğer komutların desteği ile daha kapsamlı çözümler üretilebilir. Bu konuya örnekler bölümünde değineceğim. Öncelikle komutumuzun en temel kullanım biçimine bakalım:

split [opsiyonlar]... [giriş [ekler]]

Bu arada, split komutu eğer parça ifadesi komut içerisinde belirtilmezse dosyaları ön tanımlı değer olan 1000 satır üzerinden bölecektir. Örnek işlemlerde Emissions Data.csv içeriğini kullanacağım1. Dosya içeriğine dair ön bilgilerimizi edinelim.

ls -l Emissions_Data.csv
wc -l Emissions_Data.csv
head Emissions_Data.csv

Dosya boyutu ~28Kb ve içeriğinde başlıklar hariç 788 satır barındırmakta. İlk satır ise Year, Country, Continent ve Emission başlıklarından (head -1) oluşuyor. Yazının giriş bölümlerinde de bahsi geçtiği üzere split işleminde bu başlıkları işlemin dışında tutmak isteyebiliriz. Bu maksatla tail komutu işimize yarayabilir.

tail -n 788 Emissions_Data.csv > Emissions_Data_New.csv

İşlemlerimizi başlıkların olmadığı Emissions_Data_New.csv dosyası üzerinden gerçekleştirebiliriz.

-a N, –suffix-length=N

-a (veya --suffix-length) bize uzantı-ek tanımlama imkanı sunmakta. split komutunu herhangi bir option olmaksızın kullandığımızda parçaların adlandırılması xaa gibi biçimlerde olacaktır. Bu isimlendirmedeki aa -a tarafından belirlenir ve ön tanımlı olarak 2 değerine sahiptir. Diğer yandan, isim belirtilmediği sürece isimlendirme x ile başlayacaktır.

split -a 5 Emissions_Data_New.csv

Yukarıdaki komu komut satırı arayüzü üzerinden uyguladığımızda oluşturulacak dosya adı xaaaaa şeklinde olacaktır. Bir diğer örnekte -a kullanımına ek olarak satır sayısı da verelim ve isimlendirmenin nasıl sürdüğünü görelim. Hatırlarsanız wc -l komutu ile satır sayısının 788 olduğu bilgisini almıştık.

-l NUMBER, –lines=NUMBER

split -a 5 -l 100 Emissions_Data_New.csv

Yukarıdaki komutu uygulamamızın ardından her birinde maksimum 100 satır bulunan 8 adet dosya oluşacaktır ve bu dosyaların isimlendirmeleri xaaaaa, xaaaab, xaaaac, ..., xaaaah şeklinde ilerleyecektir. split isimlendirmeyi her dosya için son karakter a’dan başlayacak şekilde dıştan içe doğru yürütür. ls -l ile dosya boyutumuzun ~27Kb (27364 bytes) olduğu bilgisine sahibiz. Dosyamızı 10Kb’lik parçalara bölmek isteyebiliriz. Unutmadan, dosya boyutunda unutulmaması gereken konu bir satırın pek çok sütundan oluşması ihtimalinde satır sayısı az olsa da dosya boyutu yüksek olabilir.

-b SIZE, –bytes=SIZE

split -a 1 -b 10000 Emissions_Data_New.csv new

Komutu uyguladığımızda, newa, newb, newc isimli 3 adet dosya üretilecektir. Ek bir not, dosya isimlendirilmesindeki sıralama sayesinde dosyalarımızı kolaylıkla birleştirebiliriz.

cat new* > Emissions_Data.csv

Örneklerimizi biraz daha geliştirelim. Örneklendirme öncesinde başlıkları (header) alanını hariç tutarak yeni bir dosya oluşturmuş ve işlemlerimizi doğrudan bu dosya üzerinden gerçekleştirmiştik. Peki, yeni bir dosya oluşturmadan işlemlerimizi yapmak ve çıktıları bu başlıklar olmadan oluşturmak istersek ne yapmalıyız?

splitCsv() {
    HEADER=$(head -1 $1)
    if [ -n "$2" ]; then
        CHUNK=$2
    else
        CHUNK=1000
    fi
    tail -n +2 $1 | split -l $CHUNK - $1_split_
    for i in $1_split_*; do
        echo -e "$HEADER\n$(cat $i)" > $i
    done
}

Yukarıdaki komut stackoverflow üzerinde paylaşılmış bir soruya istinaden2 üretilen bir fonksiyondan oluşmakta. splitCsv() fonksiyonunu komut satırı arayüzü üzerinden uyguladığımızda splitCsv Emissions_Data.csv şeklinde kullanabiliriz.

splitCsv Emissions_Data_New.csv

Yukarıdaki komutu uyguladığımızda splitCsv fonksiyonu içerisindeki tanımlamalar çerçevesinde (CHUNK=1000 (satır sayısı) ve _split_ isim eki gibi) dosyalar başlıksız olarak üretilecektir. Yukarıdaki komutu uygulayıp, ilgili fonksiyonu çağırdığımızda satır sayısı 1000’den düşük olduğu için tek dosya üretilecektir. Ancak, satır sayısı belirterek de ($2) işlem yürütebilmekteyiz.

splitCsv Emissions_Data_New.csv 300

Oluşturulacak dosyalar newData.csv_split_aa, newData.csv_split_ab, newData.csv_split_ac şeklinde adlandırılacaklardır. Fonksiyon içeriğini satır yerine (-l) dosya boyutu (-b) temel alınacak şekilde de düzenleyebilirsiniz. İlgili işlemi AWK komutu ile gerçekleştirmek için aşağıdaki komutu uygulayabilirsiniz3.

awk -v l=500 '(NR==1){header=$0;next}
    (NR%l==2) {
        c=sprintf("%0.5d",c+1);
        close(file); file=FILENAME; sub(/csv$/,c".csv",file)
        print header > file
    }
{print $0 > file}' Emissions_Data.csv

Bu komut uygulandığında, oluşturulan dosyalar newData.00001.csv, newData.00002.csv ve newData.00003.csv şeklinde isimlendirileceklerdir.

Bir diğer örnekte ise, başlıkları (Year, Country, Continent ve Emission) oluşturulan her dosyanın ilk satırına ekleyelim4.

splitWithHeader() {
    HEADER=$(head -1 $1)
    if [ -n "$2" ]; then
        CHUNK=$2
    else
        CHUNK=500
    fi
tail -n +2 $1 | split -l $CHUNK - split_
for file in split_*
do
    head -n 1 $1 > tmp_file
    cat $file >> tmp_file
    mv -f tmp_file $file
done
}

Yukarıdaki splitWithHeader() fonksiyonu ile belirttiğimiz dosya standart değerler dışında (CHUNK=1000 ve split_ isim eki) bir değer tanımlanmamışsa belirtilen dosyayı (Emissions_Data.csv) en fazla 500 satır içerecek şekilde parçalara bölecek ve her parça için split_aa, split_ab şeklinde isimlendirmeler oluşturacaktır. Bu dosyaları görüntülediğinizde her dosyanın ilk satırında Year, Country, Continent ve Emission başlıklarının da olduğunu görebilirsiniz.

Split komutu örneklerde de görüldüğü üzere oldukça basit bir kullanıma sahip. Komut ile ilgili daha detaylı bilgi almak için her zaman olduğu gibi man split komutunu kullanabiliriz. Ek olarak, standart split komutu dışında benzer işlemleri çok daha kapsamlı option seçenekleriyle birlikte csplit ile de gerçekleştirmek mümkün.