Perintah dirname Linux: mengambil jalur direktori dari nama file

Perintah dirname mengambil bagian direktori dari string jalur dengan membuang komponen terakhirnya. Misalnya, /home/user/report.txt menghasilkan /home/user; gunakan bersama basename untuk mengambil nama terakhir jika Anda perlu memisahkan kedua bagian dalam skrip.

dirname sebenarnya tidak menelusuri sistem file atau memeriksa keberadaan direktori induk. Ia menerapkan aturan yang telah ditentukan sebelumnya pada string input, jadi jika Anda perlu menyelesaikan jalur absolut atau tautan simbolik yang sebenarnya, Anda harus menggunakan perintah seperti realpath.

Apa itu perintah dirname?

Untuk mendapatkan bagian dari jalur lengkap tanpa komponen terakhir, jalankan seperti berikut.

dirname /home/user/report.txt

Keluaran adalah sebagai berikut.

/home/user

Ia tidak memeriksa apakah nama terakhir yang dimasukkan adalah file atau direktori yang sebenarnya. Karena ini adalah pemrosesan string sederhana, aturan yang sama berlaku bahkan untuk jalur yang tidak ada.

Sintaks dasar dan penggunaan

dirname nama...

Contoh berikut memakai GNU Coreutils. GNU dirname dapat menerima beberapa jalur dan menampilkan satu hasil per baris, sedangkan sintaks POSIX hanya mensyaratkan satu argumen jalur. Periksa dirname --version dan dirname --help pada sistem target. Karena hanya mengolah string, file contoh tidak perlu dibuat terlebih dahulu.

dirname /var/log/nginx/access.log
dirname /home/user/Documents/
dirname relative/path/file.txt

Hasil yang umum adalah /var/log/nginx, /home/user, dan relative/path secara berurutan. Tanda miring di akhir dan tanda miring berturut-turut dapat berubah selama proses pembersihan, jadi jangan menggunakannya untuk mempertahankan string asli sebagaimana adanya.

Hasil berdasarkan tipe input

Input Keluaran umum
/home/user/report.txt /home/user
docs/manual.pdf docs
notes.txt .
/usr/ /
/ /

Nama tanpa tanda miring

Jika tidak ada tanda miring di input, satu titik yang mewakili direktori saat ini akan dicetak.

dirname report.txt
.

Hasil ini tidak berarti bahwa ada file bernama report.txt di direktori saat ini; ini merepresentasikan bagian direktori dalam string input.

Masukan kosong yang sengaja diberikan sebagai satu argumen, dirname '', juga menghasilkan .. Ini berbeda dari menjalankan dirname tanpa argumen, yang merupakan kesalahan pemanggilan.

Path absolut dan path root

Jika komponen terakhir dari path absolut dihapus dan hanya root yang tersisa, / dicetak.

dirname /etc
dirname /

Kedua perintah menghasilkan /. Masukan khusus // dapat dipertahankan sebagai // pada platform yang membedakannya dari /; jangan menganggap perilakunya sama pada semua sistem.

Tanda slash di akhir path

Slash yang tidak diperlukan di akhir dihapus terlebih dahulu, kemudian komponen terakhir diproses.

dirname /srv/www/site/
dirname /srv/www/site///

Kedua input umumnya menghasilkan /srv/www. Ini tidak cocok untuk tugas yang perlu mempertahankan jumlah garis miring atau garis miring akhir pada aslinya.

Memproses Beberapa Jalur

Menentukan beberapa nama sekaligus

Dalam implementasi GNU, beberapa jalur dapat dicantumkan.

dirname /srv/www/index.html /var/log/syslog /home/user/file.txt

Bagian direktori untuk setiap input ditampilkan di baris terpisah.

/srv/www
/var/log
/home/user

Pisahkan dengan NUL menggunakan -z

Dalam otomatisasi di mana nama berkas mungkin mengandung pemisah baris, Anda dapat memisahkan hasil dengan karakter NUL menggunakan -z atau --zero.

dirname -z /srv/www/index.html /var/log/syslog

Contoh tersebut menghasilkan byte /srv/www, NUL, /var/log, NUL. Program penerima juga harus memahami NUL; variabel shell biasa tidak menyimpan byte NUL dengan utuh. Opsi ini merupakan ekstensi GNU, jadi periksa dukungannya jika skrip perlu berjalan pada sistem Unix lain.

Menggunakan dirname dan basename bersama-sama

Simpan contoh lengkap berikut sebagai split-path.sh lalu jalankan sh split-path.sh. Skrip memakai shell POSIX serta utilitas dirname dan basename; tidak membuka atau mengubah jalur contoh.

#!/bin/sh
path='/home/user/docs/report.pdf'
directory=$(dirname -- "$path") || exit 1
name=$(basename -- "$path") || exit 1

printf 'Direktori: %s\n' "$directory"
printf 'Nama: %s\n' "$name"

Keluaran mengambil bentuk berikut.

Direktori: /home/user/docs
Nama: report.pdf

Kedua perintah ini berguna untuk membagi string asli menjadi dua bagian yang bermakna, tetapi ketika digabungkan kembali, mereka tidak mengembalikan garis miring ganda atau garis miring akhir dari yang asli.

Substitusi perintah $(...) menghapus baris baru di akhir keluaran. Contoh ini sesuai untuk nama biasa; nama yang berakhir dengan baris baru tidak dipertahankan dengan utuh. Jika perlu memproses nama arbitrer, pertimbangkan aliran NUL dan program penerima yang sesuai.

Menggunakan dirname dalam skrip shell

Membuat direktori induk dari file keluaran

Simpan sebagai prepare-parent.sh di direktori latihan yang dapat ditulis, lalu jalankan sh prepare-parent.sh './backups/daily/archive.tar.gz'. Skrip ini hanya menyiapkan direktori induk; file arsipnya belum dibuat. Jalur relatif mengikuti direktori kerja saat skrip dijalankan.

#!/bin/sh
if [ "$#" -ne 1 ]; then
  printf '%s\n' 'Penggunaan: sh prepare-parent.sh OUTPUT' >&2
  exit 2
fi
output=$1
output_dir=$(dirname -- "$output") || exit 1
mkdir -p -- "$output_dir" || exit 1
printf 'Direktori siap: %s\n' "$output_dir"

Untuk contoh tersebut, direktori ./backups/daily akan tersedia dan skrip menampilkan Direktori siap: ./backups/daily. Status 0 berarti berhasil, status 1 berarti pengambilan jalur atau pembuatan direktori gagal, dan status 2 berarti jumlah argumennya salah. Direktori yang sudah ada tidak dihapus.

Gunakan jalur yang Anda tentukan dan percayai untuk latihan. Untuk masukan eksternal, periksa batas direktori tujuan secara terpisah: komponen .., jalur absolut, dan tautan simbolik masih memengaruhi operasi berikutnya. dirname bukan pembatas akses dan tidak menjamin hasil tetap berada dalam direktori dasar tertentu.

Membandingkan dengan Ekspansi Parameter Shell POSIX

Untuk input sederhana, Anda dapat menghapus bagian terakhir setelah garis miring menggunakan ekspansi parameter shell.

path='/srv/www/index.html'
directory=${path%/*}
printf '%s\n' "$directory"

Hasil contoh adalah /srv/www. Ekspansi %/* membuang sufiks terpendek yang cocok dengan pola garis miring beserta bagian setelahnya. Untuk path='notes.txt', hasil ekspansi tetap notes.txt, sedangkan dirname menghasilkan .; untuk /, ekspansi menghasilkan string kosong. Uji juga jalur dengan garis miring akhir sebelum menggantikan utilitas ini dengan aturan string sendiri.

Perbedaan dirname, realpath, dan pwd

Perintah Target untuk pemrosesan Hasil utama
dirname String jalur yang dimasukkan Bagian direktori sebelum komponen terakhir
basename String jalur yang dimasukkan Nama file terakhir atau nama direktori
realpath Jalur dan sistem file yang ditentukan Jalur yang telah dinormalisasi atau jalur dengan tautan simbolis yang diselesaikan
pwd Lokasi kerja proses saat ini Jalur absolut direktori kerja saat ini

dirname ../logs/app.log menghasilkan ../logs sebagai string. Perhatikan spasi setelah nama perintah. Utilitas ini tidak mengubah hasil menjadi jalur absolut atau menyelesaikan tautan simbolik, dan komponen .. sebelum bagian terakhir tetap dipertahankan.

Ringkasan opsi utama

Opsi Deskripsi
-z, --zero Akhiri setiap hasil dengan karakter NUL, bukan baris baru.
--help Menampilkan penggunaan dan opsi yang didukung.
--version Mencetak versi GNU Coreutils yang terinstal.
-- Argumen berikutnya dianggap sebagai nama, bukan opsi.

Masalah umum

Hasilnya adalah titik tunggal

Karena nama masukan tidak mengandung garis miring. Hasil dari dirname file.txt, yang merupakan ., mewakili direktori saat ini dari perspektif string.

Direktori induk sebenarnya tidak ada

dirname tidak memeriksa sistem file. Untuk benar-benar menggunakan direktori keluaran, Anda perlu memverifikasi keberadaannya dan izin aksesnya secara terpisah.

Jalur dengan spasi atau wildcard dapat rusak

Sertakan variabel dalam tanda kutip ganda dan gunakan -- sebelum nilai yang dapat dimulai dengan tanda hubung.

path='/srv/uploads/annual report.pdf'
dirname -- "$path"

FAQ

Apakah dirname benar-benar menemukan direktori induk?

Tidak. Itu hanya menghapus komponen terakhir dari string jalur input; tidak memeriksa keberadaan jalur atau tautan simbolik secara nyata.

Mengapa dirname file.txt mencetak satu titik?

Karena tidak ada garis miring yang memisahkan direktori dalam input, itu mencetak . yang mewakili direktori saat ini.

Bisakah beberapa jalur diproses sekaligus?

GNU dirname menerima beberapa jalur sebagai argumen dan mencetak setiap hasil. Jika portabilitas dengan implementasi Unix lainnya diperlukan, periksa format yang didukung terlebih dahulu.

Bisakah saya menggunakan dirname jika saya memerlukan jalur absolut?

dirname tidak mengonversi jalur relatif menjadi jalur absolut. Jika Anda membutuhkan jalur absolut yang dinormalisasi, gunakan opsi realpath yang sesuai.

Dokumentasi resmi

Untuk konteks perintah lain, lihat referensi perintah Linux menurut tugas (bahasa Inggris). Aturan pengolahan jalur dan portabilitas tersedia dalam dokumen resmi berikut.