Ana içeriğe geç

04- Dosya ve Dizin İşlemleri

Unix türevleri ile uğraşmaya başladığınızda, karşınıza şu konsept sıklıkla çıkacaktır: Everything is a file (Her şey bir dosyadır)

Bu konsept, farklı uzmanlar arasında fikir ayrılıklarına sebep olabilmektedir. Örneğin bazıları, her şeyin aslında bir dosya değil, bir dosya tanımlayıcı (file descriptor) olduğunu savunur.

İşletim sisteminin derinlikliklerine uzanan bu tartışmalarda, ipin ucunu fazla kaybetmeden yüzeye geri çıkalım. Zira işletim sisteminin derinliklerine - gerçek anlamda - indiğimizde, bir "dosyanın" ne olduğunu bile açıklamakta güçlük çekerim.

Ancak Linux ile uğraşacaksak, gerçekten de pek çok şeyin aslında bir dosya olduğunu, bu dosyaların da azımsanamayacak bir kısmının aslında plain-text olduğunu kabul ederek hayatımıza devam edebiliriz. Bu doküman serisinin içerisinde Metin İşleme bölümünün ayrıca ele alınacak olmasının temel sebebi de budur. Çünkü... Önemli!?!

Opsiyonlar Hakkında

Bu bölümde size anlatılacak opsiyonlar kesinlikle ezberlenmemeli. Şu an için birkaç basit iş yapacağız. Fakat Yardım Alma bölümünde, komutların nasıl kullanılacağına ve hangi opsiyonların ne işe yaradığına dair bilgileri nasıl edinebileceğimizi göreceğiz.

Boş Dosya Oluşturma

Boş bir dosya oluşturmak için yapabileceğimiz pek çok şey var. Bunlardan en sık kullanılanlarından biri de touch programıdır. touch programının esas amacı, dosyalara ait zaman damgalarını (erişim tarihi, değiştirme tarihi gibi) değiştirmektir. Fakat ifade ettiğiniz dosya, hâlihazırda yoksa, touch programı - varsayılan olarak - bu dosyayı boş şekilde oluşturur.

ali@ubuntu24:~$ touch deneme
ali@ubuntu24:~$ ls
deneme
ali@ubuntu24:~$

touch deneme komutu ile, "deneme" dosyasının zaman damgalarını değiştirmek istediğimizi belirttik. Fakat böyle bir dosya hâlihazırda bulunmadığı için bizim için oluşturuldu. Oluşturulan yeni dosyayı, ls programı sayesinde görebildik.

touch programı ile birden fazla dosyayı aynı anda oluşturmak da mümkün:

ali@ubuntu24:~$ touch muzik resim deneme
ali@ubuntu24:~$ ls
deneme  muzik  resim
ali@ubuntu24:~$

touch muzik resim deneme komutu ile, 3 farklı dosya oluşturmak istediğimizi belirttik. "deneme" dosyası zaten var olduğu için sadece erişim ve değiştirme tarihleri değiştirildi. "muzik" ve "resim" dosyaları olmadığı için, o dosyalar boş şekilde oluşturuldu.

Boş Dizin Oluşturma

Dizin oluşturmak için mkdir programını kullanırız. touch programına benzer şekilde, bir veya birden fazla dizini tek seferde oluşturabiliriz.

ali@ubuntu24:~$ mkdir tatil
ali@ubuntu24:~$ ls
deneme  muzik  resim  tatil
ali@ubuntu24:~$ mkdir evraklar projeler tatil fotoğrafları
mkdir: cannot create directory ‘tatil’: File exists
ali@ubuntu24:~$ ls
deneme  evraklar  fotoğrafları  muzik  projeler  resim  tatil

Yukarıdaki çıktıları inceleyelim. mkdir tatil komutu ile "tatil" isimli bir dizin oluşturduk. ls ile listeledik ve "tatil" dizinini görebildik. Sonrasında ise "evraklar", "projeler" ve "tatil fotoğrafları" isimli 3 farklı dizin oluşturmayı denedik(!). Ancak başarılı olamadık.

Shell ile Tanışma yazısında bahsettiğimiz gibi, boşluk karakteri Bash için bir ayraçtır. Argümanları ayırır. Bu durumda Bash; komutumuzu "evraklar", "projeler", "tatil" ve "fotoğrafları" isimli dizinler oluşturacak şekilde yorumladı. Üstelik, "tatil" isimli dizini oluşturamadık. Çünkü zaten var. Fakat diğer dizinler - "fotoğrafları" dizini de dâhil, oluşturuldu.

Hatırlarsanız daha önce, çalıştırdığımız komutların hata ile karşılaşmadığı durumda sessizce işini yapacağından, fakat hata oluştuğunda bize haber vereceğinden bahsetmiştik. Yukarıda, bu durumun bir örneğini görüyoruz.

İsminde Boşluk Geçen Dosyalar

Bash'in boşluk karakterini bir ayraç olarak değil, gerçekten string bir boşluk olarak yorumlamasını istiyorsak, bunu şu 2 şekilde sağlayabiliriz. Birincisi, dosya ismini tırnak işaretleri arasına alabiliriz. mkdir "tatil fotoğrafları" gibi. İkinci bir yöntem olarak ise, escape character dediğimiz özel karakteri kullanabiliriz. Bu konuya daha sonra değineceğiz. Fakat şu an için, mkdir tatil\ fotoğrafları gibi bir kullanım şekli olduğundan bahsedebiliriz.

Dosya ve Dizin Kopyalama

Kopyalama işlemlerimiz için cp programını kullanabiliriz. Kabaca, cp kaynak hedef şeklinde bir kullanımı vardır.

ali@ubuntu24:~$ ls
deneme  evraklar  fotoğrafları  muzik  projeler  resim  tatil
ali@ubuntu24:~$ cp muzik house
ali@ubuntu24:~$ ls
deneme  evraklar  fotoğrafları  house  muzik  projeler  resim  tatil

Yukarıdaki örnekte, ls ile var olan dosyalarımızı listeledik. Devamında "muzik" dosyasının bir kopyasını, "house" ismiyle oluşturmak istedik. Tekrar listelediğimizde ise dosyamızın bir kopyasını oluşturmuş olduk.

Aynı işlemi, "tatil" dizini için deneyelim:

ali@ubuntu24:~$ cp tatil izmir
cp: -r not specified; omitting directory 'tatil'

cp programı, varsayılan olarak dosyaları kopyalar. Bir dizini, tüm içeriği ile birlikte kopyalamak için "-R, -r, --recursive" opsiyonlarından herhangi birini kullanabiliriz. Aldığımız hata mesajı da zaten buna benzer bir öneride bulunuyor.

ali@ubuntu24:~$ cp -r tatil izmir
ali@ubuntu24:~$ ls
deneme  evraklar  fotoğrafları  house  izmir  muzik  projeler  resim  tatil

"-r" opsiyonu sayesinde, "tatil" dizininin bir kopyasını, "izmir" olarak oluşturduk.

Şimdi de "deneme" dosyasını, "projeler" dizini içine kopyalayalım:

ali@ubuntu24:~$ cp deneme projeler/
ali@ubuntu24:~$ ls
deneme  evraklar  fotoğrafları  house  izmir  muzik  projeler  resim  tatil
ali@ubuntu24:~$ ls projeler/
deneme

İlk komut ile, kaynak dosya olarak "deneme" dosyasını gösterdik. Hedef olarak ise "projeler" dizinini belirttik. ls ile baktığımızda hiçbir değişiklik yok. Normal. Fakat ls projeler/ komutu ile, "projeler" dizininin içini listelediğimizde, orada "deneme" dosyasını görüyoruz.

Sondaki "/" Karakteri

Dizinleri belirtirken sonlarında yer alan "/" karakterini her zaman koymak zorunda değilsiniz. Fakat komutlarınızı otomatik tamamlattığınızda (TAB ile), Bash bu işareti koyacaktır. Bu, esasında iyi bir pratiktir. Komutunuzu yazarken neyin dosya, neyin dizin olduğunu rahatlıkla görebilmenize olanak tanır.

Kopyalama sırasında hedef belirtirken, farklı bir dosya ismi de verebilirsiniz. Yani "deneme" dosyasını, "projeler" dizini içerisinde, "web projesi" gibi bir isimle kopyalayabiliriz. Dikkat edin! Dosya isminde boşluk olduğu için tırnak işaretlerini kullanmalıyız.

ali@ubuntu24:~$ cp deneme "projeler/web projesi"
ali@ubuntu24:~$ ls projeler/
 deneme  'web projesi'
ali@ubuntu24:~$

Gördüğünüz gibi "deneme" dosyasını, farklı bir isimle kopyalamış olduk.

Taşıma & Yeniden Adlandırma

Bu iki konu için de mv programını kullanabiliriz. Hedef olarak bir dizin belirtirsek, kaynak dosyamızı oraya taşır. Şayet bir dizin belirtmezsek, dosyanın ya da dizinin ismini değiştirir.

ali@ubuntu24:~$ ls
deneme  evraklar  fotoğrafları  izmir  muzik  projeler  resim  tatil
ali@ubuntu24:~$ mv deneme örnek
ali@ubuntu24:~$ ls
evraklar  fotoğrafları  izmir  muzik  örnek  projeler  resim  tatil
ali@ubuntu24:~$ mv fotoğrafları "tatil fotoğrafları"
ali@ubuntu24:~$ ls
evraklar   izmir   muzik   örnek   projeler   resim   tatil  'tatil fotoğrafları'

mv deneme örnek ile, "deneme" dosyasının adını "örnek" olarak değiştirdik. mv fotoğrafları "tatil fotoğrafları" komutu ile, "fotoğrafları" isimli dizinin adını "tatil fotoğrafları" olarak değiştirdik.

ali@ubuntu24:~$ ls
evraklar   izmir   muzik   örnek   projeler   resim   tatil  'tatil fotoğrafları'
ali@ubuntu24:~$ mv örnek evraklar/
ali@ubuntu24:~$ mv resim evraklar/
ali@ubuntu24:~$ ls
evraklar   izmir   muzik   projeler   tatil  'tatil fotoğrafları'
ali@ubuntu24:~$ ls evraklar/
örnek  resim

Burada ise sırasıyla "örnek" ve "resim" dosyalarını "evraklar" dizini içerisine taşıdık. ls ile tekrar baktık ve bu dosyaları göremedik. ls evraklar/ ile "evraklar" dizininin içeriğini listelediğimizde ise, "örnek" ve "resim" isimli 2 dosyamızın buraya taşındığını gördük.

Boş Dizinleri Silme

rmdir komutu ile, içi boş olan dizinleri silebiliriz.

ali@ubuntu24:~$ ls
evraklar   izmir   muzik   projeler   tatil  'tatil fotoğrafları'
ali@ubuntu24:~$ rmdir izmir
rmdir: failed to remove 'izmir': Directory not empty
ali@ubuntu24:~$ rmdir tatil
ali@ubuntu24:~$ ls
evraklar   izmir   muzik   projeler  'tatil fotoğrafları'

rmdir izmir komutu ile "izmir" dizinini silmek istedik. Fakat dizin boş olmadığı için komutumuz hata verdi. rmdir tatil komutu ile ise "tatil" dizinini silmek istedik ve herhangi bir sorun ile karşılaşmadık.

Dosya ve Dolu Dizinleri Silme

Her iki işlem için de rm programını kullanacağız.

ali@ubuntu24:~$ ls
evraklar   izmir   muzik   projeler  'tatil fotoğrafları'
ali@ubuntu24:~$ rm muzik
ali@ubuntu24:~$ ls
evraklar   izmir   projeler  'tatil fotoğrafları'
ali@ubuntu24:~$ rm izmir
rm: cannot remove 'izmir': Is a directory
ali@ubuntu24:~$ ls
evraklar   izmir   projeler  'tatil fotoğrafları'
ali@ubuntu24:~$ rm -r izmir
ali@ubuntu24:~$ ls
evraklar   projeler  'tatil fotoğrafları'

rm muzik komutu ile "muzik" dosyasını sildik. rm izmir komutu ile dizini silmeyi denedik fakat bu sefer de bir dizin olduğu için silemedik. Daha sonra rm -r izmir komutu ile bu dizini ve içindeki dosyaları silebildik. Tıpkı cp programına benzer şekilde, rm programı da dizinler üzerinde çalışabilmek için "-r, -R veya --recursive" opsiyonlarına ihtiyaç duyar.

Opsiyonlar Hakkında Tekrar Hatırlatma

Buraya kadar olan kısımda birkaç komut gördük. Bunlarla birtakım işlemler yaptık. Bazı opsiyonlara ihtiyaç duyduk. Ancak tekrar etmekte yarar görüyorum. Bu opsiyonlar ezberlenecek şeyler değil. Yardım Alma bölümünde, bu opsiyonların listesine nasıl ulaşacağımızdan detaylıca bahsedeceğiz.

Komut mu, program mı?

İfadelerimde bazen komut, bazen program kullandığımı fark etmiş olabilirsiniz. "Komut"; CLI'a yazıp, "Enter"a basıp gönderdiğiniz satırdır. Bizim burada kullandığımız ls, cp, mv gibi araçlar ise birer "program"dır. Internal ve External Komutlar bölümünde, bu ayrımdan daha detaylı bahsedeceğiz. Bu ayrımı bilmek çok önemli olmakla birlikte, bu iki kelimenin birbiri yerine kullanıldığına da - maalesef - şahit olacaksınız.

Metin Dosyalarını Okuma

Metin (text) dosyalarını okumak için kullanabileceğimiz birçok araç mevcut. Bunlardan birkaçına değineceğiz.

Okunacak Dosyalar

Bu bölümde bazı dosyalar okuyacağız. Bu dosyaların ne olduğu ve ne işe yaradığı, şu an için bizi ilgilendirmeyecek.

cat

Dosyaların içeriğini okumak için kullanabileceğimiz programlardan biri cat. cat, dosyaları birleştirir ve çıktıyı ekranınıza yazar. Şayet tek dosya verirseniz, sadece bir dosyayı okumanıza olanak sağlar.

ali@ubuntu24:~$ cat /etc/passwd
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/run/ircd:/usr/sbin/nologin
_apt:x:42:65534::/nonexistent:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
systemd-network:x:998:998:systemd Network Management:/:/usr/sbin/nologin
systemd-timesync:x:997:997:systemd Time Synchronization:/:/usr/sbin/nologin
dhcpcd:x:100:65534:DHCP Client Daemon,,,:/usr/lib/dhcpcd:/bin/false
messagebus:x:101:102::/nonexistent:/usr/sbin/nologin
systemd-resolve:x:992:992:systemd Resolver:/:/usr/sbin/nologin
pollinate:x:102:1::/var/cache/pollinate:/bin/false
polkitd:x:991:991:User for polkitd:/:/usr/sbin/nologin
syslog:x:103:104::/nonexistent:/usr/sbin/nologin
uuidd:x:104:105::/run/uuidd:/usr/sbin/nologin
tcpdump:x:105:107::/nonexistent:/usr/sbin/nologin
tss:x:106:108:TPM software stack,,,:/var/lib/tpm:/bin/false
landscape:x:107:109::/var/lib/landscape:/usr/sbin/nologin
fwupd-refresh:x:989:989:Firmware update daemon:/var/lib/fwupd:/usr/sbin/nologin
usbmux:x:108:46:usbmux daemon,,,:/var/lib/usbmux:/usr/sbin/nologin
ali:x:1000:1000:Ali:/home/ali:/bin/bash
sshd:x:109:65534::/run/sshd:/usr/sbin/nologin
ali@ubuntu24:~$

cat /etc/passwd komutu ile, "/etc/passwd" dosyasını okumak istediğimizi belirttik. Bu dosyanın içeriği, shell'imize geldi. cat programının "-n" opsiyonu ile, okunan dosyaya satır numaraları eklemek de mümkün:

ali@ubuntu24:~$ cat -n /etc/apt/sources.list.d/ubuntu.sources
     1  Types: deb
     2  URIs: http://archive.ubuntu.com/ubuntu/
     3  Suites: noble noble-updates noble-backports
     4  Components: main restricted universe multiverse
     5  Signed-By: /usr/share/keyrings/ubuntu-archive-keyring.gpg
     6
     7  Types: deb
     8  URIs: http://security.ubuntu.com/ubuntu/
     9  Suites: noble-security
    10  Components: main restricted universe multiverse
    11  Signed-By: /usr/share/keyrings/ubuntu-archive-keyring.gpg

nl

nl programı, bir dosyadaki satırları numaralandırarak ekrana yazar. nl programı ile, cat -n çıktısına benzer bir çıktı alabiliriz.

ali@ubuntu24:~$ nl /etc/crontab
     1  # /etc/crontab: system-wide crontab
     2  # Unlike any other crontab you don't have to run the `crontab'
     3  # command to install the new version when you edit this file
     4  # and files in /etc/cron.d. These files also have username fields,
     5  # that none of the other crontabs do.

     6  SHELL=/bin/sh
     7  # You can also override PATH, but by default, newer versions inherit it from the environment
     8  #PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

     9  # Example of job definition:
    10  # .---------------- minute (0 - 59)
    11  # |  .------------- hour (0 - 23)
    12  # |  |  .---------- day of month (1 - 31)
    13  # |  |  |  .------- month (1 - 12) OR jan,feb,mar,apr ...
    14  # |  |  |  |  .---- day of week (0 - 6) (Sunday=0 or 7) OR sun,mon,tue,wed,thu,fri,sat
    15  # |  |  |  |  |
    16  # *  *  *  *  * user-name command to be executed
    17  17 *    * * *   root    cd / && run-parts --report /etc/cron.hourly
    18  25 6    * * *   root    test -x /usr/sbin/anacron || { cd / && run-parts --report /etc/cron.daily; }
    19  47 6    * * 7   root    test -x /usr/sbin/anacron || { cd / && run-parts --report /etc/cron.weekly; }
    20  52 6    1 * *   root    test -x /usr/sbin/anacron || { cd / && run-parts --report /etc/cron.monthly; }
    21  #

more

more, dosya içeriklerini sayfa sayfa okumamızı sağlayan bir sayfalayıcıdır (pager). Kullanımı, cat ve nl programlarına benzer olmakla birlikte, en önemli farkı, içeriği tek seferde değil, sayfa sayfa vermesidir.

ali@ubuntu24:~$ more /var/log/auth.log
2025-09-07T23:42:04.794798+00:00 ubuntu24 useradd[844]: new group: name=ali, GID=1000
2025-09-07T23:42:04.794801+00:00 ubuntu24 useradd[844]: new user: name=ali, UID=1000, GID=1000, home=/home/ali, shell=/bin/bash, from=none
2025-09-07T23:42:04.794803+00:00 ubuntu24 useradd[844]: add 'ali' to group 'adm'
2025-09-07T23:42:04.794804+00:00 ubuntu24 useradd[844]: add 'ali' to group 'cdrom'
2025-09-07T23:42:04.794807+00:00 ubuntu24 useradd[844]: add 'ali' to group 'sudo'
2025-09-07T23:42:04.794829+00:00 ubuntu24 useradd[844]: add 'ali' to group 'dip'
2025-09-07T23:42:04.794835+00:00 ubuntu24 useradd[844]: add 'ali' to group 'plugdev'
2025-09-07T23:42:04.794838+00:00 ubuntu24 useradd[844]: add 'ali' to group 'lxd'
2025-09-07T23:42:04.794841+00:00 ubuntu24 useradd[844]: add 'ali' to shadow group 'adm'
2025-09-07T23:42:04.794844+00:00 ubuntu24 useradd[844]: add 'ali' to shadow group 'cdrom'
2025-09-07T23:42:04.794847+00:00 ubuntu24 useradd[844]: add 'ali' to shadow group 'sudo'
2025-09-07T23:42:04.794850+00:00 ubuntu24 useradd[844]: add 'ali' to shadow group 'dip'
2025-09-07T23:42:04.794870+00:00 ubuntu24 useradd[844]: add 'ali' to shadow group 'plugdev'
2025-09-07T23:42:04.794874+00:00 ubuntu24 useradd[844]: add 'ali' to shadow group 'lxd'
2025-09-07T23:42:04.794878+00:00 ubuntu24 passwd[852]: password for 'ali' changed by 'root'
..........

more programını kullanırken, "SPACE" tuşu ile bir sonraki sayfaya geçebilir, "q" tuşu ile programdan çıkabilirsiniz.

less

more programının tersi olarak tanımlanmıştır. more programına benzer şekilde, yine bir pager'dır. Fakat içeriği sayfa sayfa göstermek yerine, satır satır gezebilmenize olanak tanır. Yön tuşlarınızı kullanarak bu gezintiyi sağlayabilirsiniz. "q" tuşu ile programdan çıkabilirsiniz.

Kullanımı yine less <dosya adı> şeklindedir. Örneğin: less /var/log/bootstrap.log

less vs. more

less programı, more programına kıyasla daha yeni ve - bence - kullanımı daha rahat olan bir programdır. Fakat karşımıza ne çıkacağını bilemeyiz. Bazen, eski bir sistemle çalışmak durumunda kalabiliriz. Bu nedenle, bu iki pager'ı da kullanabilir olmak önemlidir.

Peki Şimdi?

Aslında dosya işlemleri ile ilgili temel bazı programlara değindik. Fakat bunları daha efektif kullanabilmek için, Bağıl ve Mutlak Yol kavramına da değinmemiz gerekiyor. Tabii bu programların çok çeşitli ve işimizi oldukça kolaylaştıracak farklı opsiyonları da var. Yeri geldikçe, bunlara da değineceğiz.

Deneyin

Okurken/dinlerken her şey çok güzel ve kolay gelebilir. Lütfen bu komutları deneyin. Hatalar yapın. Kurcalayın. Aksi durumda aşinalık kazanmanız oldukça zorlaşacaktır.