result=${PWD##*/} # to assign to a variable
printf '%s\n' "${PWD##*/}" # to print to stdout
# ...more robust than echo for unusual names
# (consider a directory named -e or -n)
printf '%q\n' "${PWD##*/}" # to print to stdout, quoted for use as shell input
# ...useful to make hidden characters readable.
Perhatikan bahwa jika Anda menerapkan teknik ini dalam keadaan lain (tidak PWD, tetapi beberapa variabel lain yang memegang nama direktori), Anda mungkin perlu memotong garis miring apa pun. Di bawah ini menggunakan dukungan extglob bash untuk bekerja bahkan dengan beberapa garis miring:
dirname=/path/to/somewhere//
shopt -s extglob # enable +(...) glob syntax
result=${dirname%%+(/)}# trim however many trailing slashes exist
result=${result##*/} # remove everything before the last / that still remains
printf '%s\n'"$result"
Atau, tanpa extglob:
dirname="/path/to/somewhere//"
result="${dirname%"${dirname##*[!/]}"}" # extglob-free multi-trailing-/ trim
result="${result##*/}"# remove everything before the last /
@ Mr_Chimp yang pertama adalah operasi ekspansi parameter yang memotong sisa direktori untuk hanya menyediakan nama dasar. Saya memiliki tautan dalam jawaban saya untuk dokumentasi ekspansi parameter; jangan ragu untuk mengikuti itu jika Anda memiliki pertanyaan.
Charles Duffy
24
@stefgosselin $PWDadalah nama variabel bash bawaan ; semua nama variabel bawaan ada dalam huruf kapital semua (untuk membedakannya dari variabel lokal, yang harus selalu memiliki setidaknya satu karakter huruf kecil). result=${PWD#*/}tidak tidak mengevaluasi /full/path/to/directory; alih-alih, itu hanya menghapus elemen pertama, membuatnya path/to/directory; menggunakan dua #karakter membuat pola cocok serakah, serasi karakter sebanyak mungkin. Baca halaman ekspansi parameter, ditautkan dalam jawaban, untuk lebih lanjut.
Charles Duffy
5
Perhatikan bahwa output dari pwdtidak selalu sama dengan nilai $PWD, karena komplikasi yang timbul dari cdtautan simbolik, apakah bash memiliki -o physicalopsi yang disetel, dan sebagainya. Ini digunakan untuk menjadi sangat tidak enak di sekitar penanganan direktori automounted, di mana merekam jalur fisik bukannya yang logis akan menghasilkan jalur yang, jika digunakan, akan memungkinkan automounter untuk secara spontan menurunkan direktori yang digunakan.
Alex North-Keys
3
Bagus! Seseorang harus menulis buku untuk orang-orang tua dari Kalimantan seperti saya. Mungkin ada satu di luar sana? Itu bisa memiliki admin sys crotchity tua mengatakan hal-hal seperti, "kembali pada hari saya, kami hanya shdan cshdan jika Anda ingin kunci backspace bekerja Anda harus membaca sttyhalaman manual keseluruhan , dan kami menyukainya!"
Bukankah ini tujuan dari basenameprogram ini? Apa yang salah dengan jawaban ini selain melewatkan tanda kutip?
Nacht - Reinstate Monica
11
@Nacht basenamememang program eksternal yang melakukan hal yang benar, tetapi menjalankan setiap program eksternal untuk hal pesta dapat melakukan out-of-the-box dengan hanya menggunakan built-in fungsi konyol, menimbulkan dampak kinerja ( fork(), execve(), wait(), dll) untuk tak ada alasan.
Charles Duffy
3
... sebagai tambahan, keberatan saya untuk di basenamesini tidak berlaku dirname, karena dirnamememiliki fungsi yang ${PWD##*/}tidak - mengubah string tanpa garis miring ., misalnya. Jadi, sementara menggunakan dirnamesebagai alat eksternal memiliki overhead kinerja, itu juga memiliki fungsi yang membantu untuk mengkompensasi yang sama.
Charles Duffy
4
@LouisMaddox, sedikit kibitzing: functionKata kuncinya adalah POSIX-tidak cocok tanpa menambahkan nilai apa pun atas sintaks standar, dan kurangnya tanda kutip akan membuat bug dalam nama direktori dengan spasi. wdexec() { "./$(basename "$PWD")"; }mungkin menjadi alternatif yang lebih disukai.
Charles Duffy
28
Tentu menggunakan basenamekurang "efisien". Tapi itu mungkin lebih efisien dalam hal produktivitas pengembang karena mudah diingat dibandingkan dengan sintaksis jelek. Jadi, jika Anda mengingatnya, lakukanlah. Kalau tidak, basenameberfungsi juga. Adakah yang pernah harus meningkatkan "kinerja" skrip bash dan membuatnya lebih efisien?
@ jocap ... kecuali bahwa penggunaan gema di sana, tanpa mengutip argumen, salah . Jika nama direktori memiliki banyak spasi, atau karakter tab, itu akan diciutkan menjadi satu spasi; jika memiliki karakter wildcard, itu akan diperluas. Penggunaan yang benar akan echo "${PWD##*/}".
Charles Duffy
9
@ jocap ... juga, saya tidak yakin bahwa "gema" sebenarnya adalah bagian sah dari jawabannya. Pertanyaannya adalah bagaimana mendapatkan jawabannya, bukan bagaimana mencetak jawabannya; jika tujuannya adalah untuk menetapkannya ke variabel, misalnya, name=${PWD##*/}akan benar, dan name=$(echo "${PWD##*/}")akan salah (dalam arti tidak perlu-inefisiensi).
Charles Duffy
24
Anda dapat menggunakan kombinasi pwd dan basename. Misalnya
Tolong jangan. Backtick membuat subkulit (dengan demikian, operasi fork) - dan dalam hal ini, Anda menggunakannya dua kali ! [Sebagai tambahan, meskipun berdalih gaya - nama variabel harus huruf kecil kecuali Anda mengekspornya ke lingkungan atau itu adalah kasus khusus, khusus].
Charles Duffy
11
dan sebagai backtics quibble gaya kedua harus diganti dengan $ (). masih bercabang tetapi lebih mudah dibaca dan dengan lebih sedikit bantuan dibutuhkan.
Jeremy Wall
1
Berdasarkan konvensi, variabel lingkungan (PATH, EDITOR, SHELL, ...) dan variabel shell internal (BASH_VERSION, RANDOM, ...) sepenuhnya dikapitalisasi. Semua nama variabel lainnya harus huruf kecil. Karena nama variabel peka terhadap huruf besar-kecil, konvensi ini menghindari variabel lingkungan dan internal yang sengaja ditimpa.
Rany Albeg Wein
2
Tergantung pada konvensi. Orang bisa berpendapat bahwa semua variabel shell adalah variabel lingkungan (tergantung pada shell), dan dengan demikian semua variabel shell harus dalam huruf kapital semua. Orang lain dapat berdebat berdasarkan ruang lingkup - variabel global semuanya terbatas, sedangkan variabel lokal lebih kecil, dan ini semua adalah global. Namun yang lain mungkin berpendapat bahwa membuat variabel huruf besar semua menambah lapisan kontras dengan perintah skrip shell, yang juga semua huruf kecil tapi bermakna kata-kata bermakna. Saya mungkin atau mungkin tidak / setuju / dengan salah satu argumen itu, tetapi saya telah melihat ketiganya digunakan. :)
tidak akan merekomendasikan karena tampaknya mendapatkan beberapa informasi warna sedangkan pwd | xargs basenametidak .. mungkin tidak begitu penting tetapi jawaban lainnya lebih sederhana dan lebih konsisten di seluruh lingkungan
davidhq
8
Saya suka jawaban yang dipilih (Charles Duffy), tetapi hati-hati jika Anda berada di direktori yang disinkronkan dan Anda ingin nama direktori target. Sayangnya saya tidak berpikir itu bisa dilakukan dalam ekspresi ekspansi parameter tunggal, mungkin saya salah. Ini seharusnya bekerja:
FYI, ${PWD##*/}adalah POSIX sh - setiap modern / bin / sh (termasuk tanda hubung, abu, dll) mendukungnya; untuk menekan Bourne yang sebenarnya pada kotak baru-baru ini, Anda harus menggunakan sistem Solaris yang agak tua. Di luar itu - echo "$PWD"; meninggalkan tanda kutip menyebabkan bug (jika nama direktori memiliki spasi, karakter wildcard, dll).
Charles Duffy
1
Ya, saya menggunakan sistem Solaris yang oldish. Saya telah memperbarui perintah untuk menggunakan kutipan.
secara mengejutkan? hanya bercanda, tetapi yang lain jauh lebih pendek dan lebih mudah diingat
codewandler
Ini cukup lucu = P Belum pernah mendengar tentang $ IFS (pemisah bidang internal) sebelum ini. pesta saya terlalu tua, tetapi dapat mengujinya di sini: jdoodle.com/test-bash-shell-script-online
Stan Kurdziel
5
Menggunakan:
basename "$PWD"
ATAU
IFS=/
var=($PWD)
echo ${var[-1]}
Ubah Internal Filename Separator (IFS) kembali ke ruang kosong.
Membutuhkan lebih banyak tanda kutip untuk menjadi benar - seperti itu, output dari pwdstring-split dan glob-diperluas sebelum diteruskan ke basename.
Charles Duffy
Jadi, basename "$(pwd)"- meskipun itu sangat tidak efisien dibandingkan dengan adil basename "$PWD", yang dengan sendirinya tidak efisien dibandingkan dengan menggunakan ekspansi parameter alih-alih memanggil basenamesama sekali.
Ini dalam semua hal versi yang lebih buruk dari jawaban yang sebelumnya diberikan oleh Arkady ( stackoverflow.com/a/1371267/14122 ): xargsFormultion tidak efisien dan bermasalah ketika nama direktori berisi baris baru atau karakter kutipan, dan formulasi kedua memanggil pwdperintah dalam subkulit, alih-alih mengambil hasil yang sama melalui ekspansi variabel bawaan.
Charles Duffy
@CharlesDuffy Namun, apakah itu jawaban yang valid dan praktis untuk pertanyaan itu.
bachph
1
Jika Anda hanya ingin melihat direktori saat ini di wilayah bash prompt, Anda dapat mengedit .bashrcfile di ~. Ubah \wke \Wdalam baris:
Anda dapat menggunakan utilitas basename yang menghapus awalan yang diakhiri dengan / dan akhiran (jika ada dalam string) dari string, dan mencetak hasilnya pada output standar.
FYI, itu tidak datang dengan distribusi Ubuntu saya.
Katastic Voyage
@KatasticVoyage, ada di Ubuntu, hanya dipanggil di basenamesana. Ini biasanya dipanggil gbasenamepada MacOS dan platform lain yang jika tidak dikirimkan dengan nama pengguna non-GNU.
Charles Duffy
-1
Perintah berikut ini akan menghasilkan pencetakan direktori kerja Anda saat ini dalam skrip bash.
(1) Saya tidak yakin di mana kami memastikan bahwa daftar argumen sedemikian rupa sehingga $1akan berisi direktori kerja saat ini. (2) The pushddanpopd tidak ada gunanya di sini karena apa pun di dalam backticks dilakukan dalam subkulit - sehingga tidak dapat memengaruhi direktori induk shell untuk memulainya. (3) Menggunakan "$(cd "$1"; pwd)"akan lebih mudah dibaca dan tahan terhadap nama direktori dengan spasi.
Jawaban:
Tidak perlu basename, dan terutama tidak perlu untuk menjalankan pwd subkulit (yang menambahkan operasi garpu tambahan, dan mahal ); shell dapat melakukan ini secara internal menggunakan ekspansi parameter :
Perhatikan bahwa jika Anda menerapkan teknik ini dalam keadaan lain (tidak
PWD
, tetapi beberapa variabel lain yang memegang nama direktori), Anda mungkin perlu memotong garis miring apa pun. Di bawah ini menggunakan dukungan extglob bash untuk bekerja bahkan dengan beberapa garis miring:Atau, tanpa
extglob
:sumber
$PWD
adalah nama variabel bash bawaan ; semua nama variabel bawaan ada dalam huruf kapital semua (untuk membedakannya dari variabel lokal, yang harus selalu memiliki setidaknya satu karakter huruf kecil).result=${PWD#*/}
tidak tidak mengevaluasi/full/path/to/directory
; alih-alih, itu hanya menghapus elemen pertama, membuatnyapath/to/directory
; menggunakan dua#
karakter membuat pola cocok serakah, serasi karakter sebanyak mungkin. Baca halaman ekspansi parameter, ditautkan dalam jawaban, untuk lebih lanjut.pwd
tidak selalu sama dengan nilai$PWD
, karena komplikasi yang timbul daricd
tautan simbolik, apakah bash memiliki-o physical
opsi yang disetel, dan sebagainya. Ini digunakan untuk menjadi sangat tidak enak di sekitar penanganan direktori automounted, di mana merekam jalur fisik bukannya yang logis akan menghasilkan jalur yang, jika digunakan, akan memungkinkan automounter untuk secara spontan menurunkan direktori yang digunakan.sh
dancsh
dan jika Anda ingin kunci backspace bekerja Anda harus membacastty
halaman manual keseluruhan , dan kami menyukainya!"Gunakan
basename
programnya. Untuk kasus Anda:sumber
basename
program ini? Apa yang salah dengan jawaban ini selain melewatkan tanda kutip?basename
memang program eksternal yang melakukan hal yang benar, tetapi menjalankan setiap program eksternal untuk hal pesta dapat melakukan out-of-the-box dengan hanya menggunakan built-in fungsi konyol, menimbulkan dampak kinerja (fork()
,execve()
,wait()
, dll) untuk tak ada alasan.basename
sini tidak berlakudirname
, karenadirname
memiliki fungsi yang${PWD##*/}
tidak - mengubah string tanpa garis miring.
, misalnya. Jadi, sementara menggunakandirname
sebagai alat eksternal memiliki overhead kinerja, itu juga memiliki fungsi yang membantu untuk mengkompensasi yang sama.function
Kata kuncinya adalah POSIX-tidak cocok tanpa menambahkan nilai apa pun atas sintaks standar, dan kurangnya tanda kutip akan membuat bug dalam nama direktori dengan spasi.wdexec() { "./$(basename "$PWD")"; }
mungkin menjadi alternatif yang lebih disukai.basename
kurang "efisien". Tapi itu mungkin lebih efisien dalam hal produktivitas pengembang karena mudah diingat dibandingkan dengan sintaksis jelek. Jadi, jika Anda mengingatnya, lakukanlah. Kalau tidak,basename
berfungsi juga. Adakah yang pernah harus meningkatkan "kinerja" skrip bash dan membuatnya lebih efisien?
sumber
echo "${PWD##*/}"
.name=${PWD##*/}
akan benar, danname=$(echo "${PWD##*/}")
akan salah (dalam arti tidak perlu-inefisiensi).Anda dapat menggunakan kombinasi pwd dan basename. Misalnya
sumber
Bagaimana dengan grep:
sumber
pwd | xargs basename
tidak .. mungkin tidak begitu penting tetapi jawaban lainnya lebih sederhana dan lebih konsisten di seluruh lingkunganSaya suka jawaban yang dipilih (Charles Duffy), tetapi hati-hati jika Anda berada di direktori yang disinkronkan dan Anda ingin nama direktori target. Sayangnya saya tidak berpikir itu bisa dilakukan dalam ekspresi ekspansi parameter tunggal, mungkin saya salah. Ini seharusnya bekerja:
Untuk melihat ini, percobaan:
melaporkan "bilah"
DIRNAME
Untuk menampilkan direktori terkemuka dari sebuah path (tanpa mengeluarkan fork-exec dari / usr / bin / dirname):
Ini misalnya akan mengubah foo / bar / baz -> foo / bar
sumber
readlink -f
ini adalah ekstensi GNU, dan karenanya tidak tersedia pada BSD (termasuk OS X).Jika Anda menggunakan shell Bourne atau
${PWD##*/}
tidak tersedia.sumber
${PWD##*/}
adalah POSIX sh - setiap modern / bin / sh (termasuk tanda hubung, abu, dll) mendukungnya; untuk menekan Bourne yang sebenarnya pada kotak baru-baru ini, Anda harus menggunakan sistem Solaris yang agak tua. Di luar itu -echo "$PWD"
; meninggalkan tanda kutip menyebabkan bug (jika nama direktori memiliki spasi, karakter wildcard, dll).Utas ini hebat! Ini satu lagi rasa:
sumber
Anehnya, tidak ada yang menyebutkan alternatif ini yang hanya menggunakan perintah bash bawaan:
Sebagai bonus tambahan, Anda dapat dengan mudah mendapatkan nama direktori induk dengan:
Ini akan bekerja pada Bash 4.3-alpha atau lebih baru.
sumber
Menggunakan:
ATAU
Ubah Internal Filename Separator (IFS) kembali ke ruang kosong.
Ada satu ruang setelah IFS.
sumber
atau
sumber
pwd
string-split dan glob-diperluas sebelum diteruskan kebasename
.basename "$(pwd)"
- meskipun itu sangat tidak efisien dibandingkan dengan adilbasename "$PWD"
, yang dengan sendirinya tidak efisien dibandingkan dengan menggunakan ekspansi parameter alih-alih memanggilbasename
sama sekali.Untuk menemukan joki di luar sana seperti saya:
sumber
$PWD
untuk"$PWD"
untuk secara benar menangani nama direktori yang tidak biasa.Saya biasanya menggunakan ini dalam skrip sh
Anda dapat menggunakan ini untuk mengotomatiskan hal-hal ...
sumber
readlink: illegal option -- f usage: readlink [-n] [file ...]
Grep bawah dengan regex juga berfungsi,
sumber
Cukup gunakan:
atau
sumber
xargs
Formultion tidak efisien dan bermasalah ketika nama direktori berisi baris baru atau karakter kutipan, dan formulasi kedua memanggilpwd
perintah dalam subkulit, alih-alih mengambil hasil yang sama melalui ekspansi variabel bawaan.Jika Anda hanya ingin melihat direktori saat ini di wilayah bash prompt, Anda dapat mengedit
.bashrc
file di~
. Ubah\w
ke\W
dalam baris:Lari
source ~/.bashrc
dan itu hanya akan menampilkan nama direktori di wilayah prompt.Ref: /superuser/60555/show-only-current-directory-name-not-full-path-on-bash-prompt
sumber
Anda dapat menggunakan utilitas basename yang menghapus awalan yang diakhiri dengan / dan akhiran (jika ada dalam string) dari string, dan mencetak hasilnya pada output standar.
sumber
Saya sangat suka menggunakan
gbasename
, yang merupakan bagian dari GNU coreutils.sumber
basename
sana. Ini biasanya dipanggilgbasename
pada MacOS dan platform lain yang jika tidak dikirimkan dengan nama pengguna non-GNU.Perintah berikut ini akan menghasilkan pencetakan direktori kerja Anda saat ini dalam skrip bash.
sumber
$1
akan berisi direktori kerja saat ini. (2) Thepushd
danpopd
tidak ada gunanya di sini karena apa pun di dalam backticks dilakukan dalam subkulit - sehingga tidak dapat memengaruhi direktori induk shell untuk memulainya. (3) Menggunakan"$(cd "$1"; pwd)"
akan lebih mudah dibaca dan tahan terhadap nama direktori dengan spasi.