mkdir Komutu: Dizin Oluşturma ve Gelişmiş Kullanımı

mkdir komutu göründüğünden çok daha güçlü bir araç. Temel dizin oluşturmanın ötesine geçip, iç içe yapılar, izin yönetimi ve web sunucusu kurulumlarında nasıl kullanacağını bu yazıda adım adım ele alıyoruz.

Sysadmin olarak günde kaç kez mkdir yazıyorsun? Muhtemelen o kadar çok ki artık düşünmeden yapıyorsun. Ama şunu sormam lazım: mkdir‘ın bütün yeteneklerini gerçekten kullanıyor musun? Çoğu kişi bu komutu sadece tek bir dizin oluşturmak için kullanıyor ve olayı orada kapatıyor. Oysa mkdir, doğru kullanıldığında seni onlarca tekrarlayan komuttan kurtarabilir, özellikle web sunucusu kurulumlarında hayat kurtarıcı oluyor.

Bu yazıda mkdir’ı sıfırdan ele alacağız. Temel kullanımdan başlayıp, gelişmiş seçeneklere, gerçek web sunucusu senaryolarına ve sık yapılan hatalara kadar her şeyi konuşacağız. Hazırsan başlayalım.

mkdir Nedir ve Ne İşe Yarar?

mkdir, “make directory” yani “dizin oluştur” anlamına gelir. Linux, macOS ve Windows’ta (hem CMD hem PowerShell üzerinden) kullanılabilen temel bir komuttur. Görevi basit: belirttiğin yerde dizin oluşturmak. Ama bu basit görevin arkasında, işini çok daha verimli yapmanı sağlayacak bir sürü parametre var.

Özellikle web sunucusu yönetimi yapıyorsan — Apache, Nginx, ya da Node.js tabanlı bir şey kuruyorsan — dizin yapılarını doğru ve hızlı oluşturmak kritik. Yanlış izinle oluşturulmuş bir dizin, saat başı dönen bir destek talebi demek. Bunu yaşadın mı biliyorum, herkes yaşadı.

Temel Kullanım

En basit haliyle mkdir şöyle çalışır:

# Tek bir dizin oluştur
mkdir mywebsite

# Tam yol belirterek dizin oluştur
mkdir /var/www/mywebsite

# Aynı anda birden fazla dizin oluştur
mkdir logs uploads cache temp

Bu kadar basit. Ama dikkat et: eğer oluşturmaya çalıştığın dizinin üst dizini yoksa, mkdir hata verir. Mesela /var/www/mywebsite/public oluşturmak istiyorsan ve mywebsite henüz yoksa, komut çakılır. İşte burada -p bayrağı devreye giriyor.

-p Parametresi: En Çok Kullandığın Seçenek Olacak

-p parametresi (“parents” yani üst dizinler) olmayan tüm üst dizinleri otomatik olarak oluşturur. Üstelik zaten var olan bir dizin için hata vermez — bunu özellikle belirtmek istiyorum çünkü script yazarken bu davranış kritik önem taşır.

# İç içe dizin yapısını tek komutla oluştur
mkdir -p /var/www/mywebsite/public_html

# Birden fazla iç içe yapı aynı anda
mkdir -p /var/www/mywebsite/{public_html,logs,ssl,backup}

# Daha karmaşık bir web projesi yapısı
mkdir -p /var/www/myproject/{public,src/{controllers,models,views},config,logs,tests}

Son komuta dikkat et. Süslü parantez genişletmesi (brace expansion) ile tek bir satırda tüm proje iskeletini oluşturuyorsun. Bu bash’ın bir özelliği, mkdir’ın değil — ama ikisini birlikte kullanınca gerçekten güçlü bir kombinasyon elde ediyorsun.

💡İpucu: Brace expansion’ı kullanırken süslü parantezler arasında boşluk bırakma. {public, src} değil {public,src} yazmalısın. Boşluk bırakırsan bash bunu tek bir string olarak yorumlar ve beklediğin sonucu alamazsın.

-m Parametresi: Dizini Oluştururken İzinleri Ayarla

Bu parametre, özellikle web sunucusu kurulumlarında seni ayrı bir chmod adımından kurtarır. Dizini oluştururken aynı anda izinlerini de belirleyebilirsin.

# 755 izniyle dizin oluştur (web dizinleri için yaygın)
mkdir -m 755 /var/www/mywebsite

# 700 izniyle gizli/hassas dizin oluştur
mkdir -m 700 /var/www/mywebsite/private

# -p ile birlikte kullanım
mkdir -m 755 -p /var/www/mywebsite/public_html

# Yalnızca sahibinin okuyabileceği log dizini
mkdir -m 600 /var/www/mywebsite/secure_logs
Uyarı: -m parametresini -p ile birlikte kullandığında dikkatli ol. -m yalnızca en son oluşturulan (hedef) dizine uygulanır, ara üst dizinlere değil. Üst dizinlerin izinleri umask değerinden etkilenir. Kritik ortamlarda her dizinin iznini ayrıca doğrula.

-v Parametresi: Ne Olduğunu Gör

-v (verbose) parametresi, oluşturulan her dizin için ekrana bilgi yazar. Script yazarken veya büyük bir yapı oluştururken gerçekten ne yapıldığını görmek istiyorsan bu bayrağı ekle.

# Verbose mod ile dizin oluştur
mkdir -pv /var/www/newsite/{public_html,logs,ssl}

# Örnek çıktı:
# mkdir: created directory '/var/www/newsite'
# mkdir: created directory '/var/www/newsite/public_html'
# mkdir: created directory '/var/www/newsite/logs'
# mkdir: created directory '/var/www/newsite/ssl'

Özellikle büyük otomasyonlarda ya da bir junior’a bir şeyler anlatırken verbose mod çok işe yarıyor. Ne oluşturuldu, ne oluşturulmadı — her şey gözünün önünde.

Tüm Parametreler Hızlı Başvuru Tablosu

ParametreUzun AdAçıklamaÖrnek
-p--parentsEksik üst dizinleri de oluşturur, var olanlar için hata vermezmkdir -p /a/b/c
-m--modeDizin izinlerini belirler (chmod formatında)mkdir -m 755 /dir
-v--verboseHer oluşturulan dizin için mesaj yazarmkdir -v /dir
-ZSELinux bağlamını varsayılana ayarlarmkdir -Z /dir
--helpYardım metnini gösterirmkdir --help
--versionSürüm bilgisini gösterirmkdir --version

Gerçek Dünya Senaryosu 1: Apache Web Sunucusu Kurulumu

Yeni bir Apache sanal sunucusu (virtual host) kuruyorsun. Standart dizin yapısını elle tek tek oluşturmak yerine aşağıdaki script’i kullan. Bu benim yıllardır kullandığım, ufak tefek geliştirdiğim bir yaklaşım.

#!/bin/bash
# Apache sanal sunucusu için dizin yapısı oluşturma scripti

DOMAIN="example.com"
WEBROOT="/var/www"
WWW_USER="www-data"

# Ana dizin yapısını oluştur
mkdir -pv ${WEBROOT}/${DOMAIN}/{public_html,logs,ssl,backup}

# Log dizini için özel izinler
mkdir -m 750 -p ${WEBROOT}/${DOMAIN}/logs

# Public HTML için doğru izinler
chmod 755 ${WEBROOT}/${DOMAIN}/public_html

# Sahipliği web sunucusu kullanıcısına ver
chown -R ${WWW_USER}:${WWW_USER} ${WEBROOT}/${DOMAIN}

# Doğrulama
ls -la ${WEBROOT}/${DOMAIN}/
echo "Dizin yapısı ${DOMAIN} için oluşturuldu."

Bu script’i /usr/local/bin/setup-vhost.sh olarak kaydedip çalıştırılabilir yaparsan, her yeni domain için tek satırla kullanabilirsin. Domain adını değişken olarak geçirmek istersen script’e parametre desteği eklemek de çok basit.

Gerçek Dünya Senaryosu 2: Nginx + PHP-FPM Projesi

Nginx kullananlar için biraz farklı bir yapı tercih ediliyor. Özellikle PHP-FPM ile çalışıyorsan, socket dosyası için ayrı bir dizin, önbellek için ayrı bir alan lazım.

# Nginx + PHP-FPM projesi için tam dizin yapısı
PROJECT="myapp"

mkdir -pv /var/www/${PROJECT}/{public,storage/{logs,cache,sessions,uploads},config}

# PHP-FPM socket dizini
mkdir -m 710 -p /run/php/${PROJECT}

# Nginx önbellek dizini
mkdir -m 755 -p /var/cache/nginx/${PROJECT}

# İzinleri ayarla
chown -R www-data:www-data /var/www/${PROJECT}/storage
chmod -R 775 /var/www/${PROJECT}/storage

# Yapıyı görüntüle
find /var/www/${PROJECT} -type d | sort
Bilgi: Laravel gibi PHP framework’leri kullanıyorsan, storage dizininin altındaki klasörlerin www-data tarafından yazılabilir olması şart. Yoksa session, cache ve log sorunlarıyla karşılaşırsın. mkdir -m 775 ile oluşturmak bu sorunu baştan çözer.

Gerçek Dünya Senaryosu 3: Node.js / Next.js Projesi

Node.js tabanlı bir uygulama deploy ediyorsun. PM2 ile çalışıyorsa log dosyaları için, statik dosyalar için ve uploads için yapıyı önceden kurmak işleri kolaylaştırır.

# Node.js projesi için dizin yapısı
APP_NAME="nextjs-app"
APP_DIR="/var/www/${APP_NAME}"

# Ana yapı
mkdir -pv ${APP_DIR}/{current,releases,shared/{logs,uploads,config}}

# PM2 log dizini
mkdir -m 755 -p /home/deploy/.pm2/logs

# Nginx statik dosyalar için
mkdir -m 755 -p /var/www/${APP_NAME}/public/static

# Sahiplik ataması (deploy kullanıcısı varsayılıyor)
chown -R deploy:deploy ${APP_DIR}
chown -R www-data:www-data ${APP_DIR}/public

echo "Node.js proje yapısı hazır: ${APP_DIR}"

Windows’ta mkdir: PowerShell ve CMD

Windows tarafında iş yapıyorsan da mkdir komutu var, hem CMD hem PowerShell’de çalışır. Ama davranış biraz farklı, bunu bilmekte fayda var.

CMD’de mkdir ve md aynı şeydir. -p bayrağına gerek yok, CMD varsayılan olarak üst dizinleri oluşturur:

# PowerShell ile tek dizin
New-Item -ItemType Directory -Path "C:inetpubmysite"

# PowerShell ile iç içe dizin yapısı (-Force var olan dizinde hata vermez)
New-Item -ItemType Directory -Force -Path "C:inetpubmysitelogs"
New-Item -ItemType Directory -Force -Path "C:inetpubmysiteuploads"
New-Item -ItemType Directory -Force -Path "C:inetpubmysitessl"

# mkdir alias'ı PowerShell'de de çalışır
mkdir -Force "C:inetpubmysitepublic"

# Birden fazla dizin oluştur (döngüyle)
$dirs = @("logs", "uploads", "ssl", "backup", "config")
foreach ($dir in $dirs) {
    New-Item -ItemType Directory -Force -Path "C:inetpubmysite$dir"
    Write-Host "Oluşturuldu: C:inetpubmysite$dir"
}
Bilgi: PowerShell’de mkdir aslında New-Item -ItemType Directory komutunun bir alias’ıdır. Her ikisi de aynı işi yapar ama script’lerde okunabilirlik açısından tam adını kullanmak daha iyidir.

Sık Yapılan Hatalar ve Çözümleri

Hata 1: “cannot create directory: No such file or directory”

Üst dizin yok, -p kullanmadın. Çözüm basit:

# Hatalı kullanım
mkdir /var/www/site/public_html  # /var/www/site henüz yok

# Doğru kullanım
mkdir -p /var/www/site/public_html

Hata 2: “Permission denied”

Hedef konumda yazma izniniz yok. sudo kullanman ya da doğru kullanıcıya geçmen gerekiyor:

# Permission denied aldığında
sudo mkdir -p /var/www/mysite

# Sonra kendi kullanıcına veya www-data'ya sahipliği ver
sudo chown -R $USER:$USER /var/www/mysite
# ya da
sudo chown -R www-data:www-data /var/www/mysite

Hata 3: Yanlış İzinle Oluşturulmuş Dizin

Umask değerin beklenenden farklı izinler üretebilir. Özellikle shared hosting ortamlarında ya da özelleştirilmiş sunucularda bu başını ağrıtabilir.

# Mevcut umask değerini kontrol et
umask

# Dizin oluşturduktan sonra izni kontrol et
ls -ld /var/www/mysite

# İzni düzelt
chmod 755 /var/www/mysite

# Alternatif: Kesin izinle mkdir kullan
mkdir -m 755 -p /var/www/mysite
Uyarı: Web dizinlerinde asla 777 izni kullanma. Bu, sunucudaki herhangi bir kullanıcının veya güvenlik açığı yoluyla saldırganın dizine yazmasına izin verir. Web sunucusu için standart olan 755 (dizinler) ve 644 (dosyalar) kombinasyonu çoğu durumda yeterlidir. Özel yazma ihtiyacı varsa sahipliği doğru kullanıcıya ata.

Bonus: Tarih Bazlı Log Dizinleri Oluşturma

Log yönetimi yapıyorsan, tarihe göre otomatik dizin oluşturmak çok işe yarıyor. Bunu cron job’a bağlarsan her gece otomatik olarak çalışır.

#!/bin/bash
# Tarih bazlı log dizini oluşturma - cron'a eklenebilir

LOG_BASE="/var/log/myapp"
DATE=$(date +%Y/%m/%d)

# Bugünün tarihine göre dizin oluştur
mkdir -pv "${LOG_BASE}/${DATE}"

# Sahipliği ayarla
chown www-data:www-data "${LOG_BASE}/${DATE}"

# 30 günden eski log dizinlerini sil
find ${LOG_BASE} -type d -mtime +30 -exec rm -rf {} + 2>/dev/null

echo "Log dizini hazır: ${LOG_BASE}/${DATE}"

Bu script’i /etc/cron.daily/ altına koyarsan sistem her gece otomatik çalıştırır. Hem yeni dizini hazırlar hem de eski logları temizler.

Özet

mkdir, basit görünümünün arkasında güçlü bir araç. Özellikle şu noktaları aklında tut:

  • -p parametresi olmadan çalışıyorsan eksik kalıyorsun. Her script’inde kullan.
  • -m ile izinleri baştan belirle, sonradan chmod ile uğraşma.
  • -v parametresi, özellikle otomasyonda debug için çok değerli.
  • Brace expansion ile tek komutta karmaşık dizin yapıları oluşturabilirsin.
  • Web sunucusu dizinlerinde izin yönetimini asla ihmal etme; 777 kesinlikle hayır.
  • Windows’ta mkdir çalışır ama PowerShell’de New-Item -ItemType Directory -Force tercih edilmeli.

Sonraki Adımlar

mkdir’ı kavradıktan sonra sıradaki adımlar şunlar olabilir:

  • chmod ve chown: Dizin izinlerini ve sahipliğini tam anlamıyla kontrol etmeyi öğren. mkdir ile başladığın iş, bu komutlarla tamamlanıyor.
  • find komutu: Oluşturduğun dizin yapılarını yönetmek, aramak ve toplu işlemler yapmak için şart.
  • Bash scripting: mkdir tek başına güçlü ama bir script içinde değişkenler, döngüler ve koşullarla birleşince gerçek gücünü ortaya koyuyor.
  • rsync ile dizin senkronizasyonu: Oluşturduğun yapıları sunucular arasında taşımak için rsync’i incele.
  • ACL (Access Control Lists): Temel chmod izinlerinin yetmediği durumlarda, ACL ile daha ince izin yönetimi yapabilirsin.

Sorun yaşıyorsan ya da farklı bir senaryon varsa yorumlarda anlat, bakıp yanıtlarım. Sysadmin dünyasında kimse her şeyi tek başına öğrenmez, paylaşmak meseleye dahil.