Bagaimana saya mendapatkan hanya nama direktori kerja saat ini dalam skrip bash, atau bahkan lebih baik, hanya perintah terminal.
pwd
memberikan path lengkap dari direktori kerja saat ini, misalnya /opt/local/bin
tetapi saya hanya inginbin
Bagaimana saya mendapatkan hanya nama direktori kerja saat ini dalam skrip bash, atau bahkan lebih baik, hanya perintah terminal.
pwd
memberikan path lengkap dari direktori kerja saat ini, misalnya /opt/local/bin
tetapi saya hanya inginbin
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 :
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 /
$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, 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.
pwd
tidak selalu sama dengan nilai $PWD
, karena komplikasi yang timbul dari cd
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
dan csh
dan jika Anda ingin kunci backspace bekerja Anda harus membaca stty
halaman manual keseluruhan , dan kami menyukainya!"
Gunakan basename
programnya. Untuk kasus Anda:
% basename "$PWD"
bin
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 berlaku dirname
, karena dirname
memiliki fungsi yang ${PWD##*/}
tidak - mengubah string tanpa garis miring .
, misalnya. Jadi, sementara menggunakan dirname
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?
$ echo "${PWD##*/}"
echo "${PWD##*/}"
.
name=${PWD##*/}
akan benar, dan name=$(echo "${PWD##*/}")
akan salah (dalam arti tidak perlu-inefisiensi).
Anda dapat menggunakan kombinasi pwd dan basename. Misalnya
#!/bin/bash
CURRENT=`pwd`
BASENAME=`basename "$CURRENT"`
echo "$BASENAME"
exit;
Bagaimana dengan grep:
pwd | grep -o '[^/]*$'
pwd | xargs basename
tidak .. mungkin tidak begitu penting tetapi jawaban lainnya lebih sederhana dan lebih konsisten di seluruh lingkungan
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:
target_PWD=$(readlink -f .)
echo ${target_PWD##*/}
Untuk melihat ini, percobaan:
cd foo
ln -s . bar
echo ${PWD##*/}
melaporkan "bilah"
Untuk menampilkan direktori terkemuka dari sebuah path (tanpa mengeluarkan fork-exec dari / usr / bin / dirname):
echo ${target_PWD%/*}
Ini misalnya akan mengubah foo / bar / baz -> foo / bar
readlink -f
ini adalah ekstensi GNU, dan karenanya tidak tersedia pada BSD (termasuk OS X).
echo "$PWD" | sed 's!.*/!!'
Jika Anda menggunakan shell Bourne atau ${PWD##*/}
tidak tersedia.
${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).
Anehnya, tidak ada yang menyebutkan alternatif ini yang hanya menggunakan perintah bash bawaan:
i="$IFS";IFS='/';set -f;p=($PWD);set +f;IFS="$i";echo "${p[-1]}"
Sebagai bonus tambahan, Anda dapat dengan mudah mendapatkan nama direktori induk dengan:
[ "${#p[@]}" -gt 1 ] && echo "${p[-2]}"
Ini akan bekerja pada Bash 4.3-alpha atau lebih baru.
Menggunakan:
basename "$PWD"
ATAU
IFS=/
var=($PWD)
echo ${var[-1]}
Ubah Internal Filename Separator (IFS) kembali ke ruang kosong.
IFS=
Ada satu ruang setelah IFS.
basename $(pwd)
atau
echo "$(basename $(pwd))"
pwd
string-split dan glob-diperluas sebelum diteruskan ke basename
.
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 basename
sama sekali.
Untuk menemukan joki di luar sana seperti saya:
find $PWD -maxdepth 0 -printf "%f\n"
$PWD
untuk "$PWD"
untuk secara benar menangani nama direktori yang tidak biasa.
Saya biasanya menggunakan ini dalam skrip sh
SCRIPTSRC=`readlink -f "$0" || echo "$0"`
RUN_PATH=`dirname "${SCRIPTSRC}" || echo .`
echo "Running from ${RUN_PATH}"
...
cd ${RUN_PATH}/subfolder
Anda dapat menggunakan ini untuk mengotomatiskan hal-hal ...
Grep bawah dengan regex juga berfungsi,
>pwd | grep -o "\w*-*$"
Cukup gunakan:
pwd | xargs basename
atau
basename "`pwd`"
xargs
Formultion tidak efisien dan bermasalah ketika nama direktori berisi baris baru atau karakter kutipan, dan formulasi kedua memanggil pwd
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:
PS1='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ '
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
Saya sangat suka menggunakan gbasename
, yang merupakan bagian dari GNU coreutils.
basename
sana. Ini biasanya dipanggil gbasename
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.
pushd .
CURRENT_DIR="`cd $1; pwd`"
popd
echo $CURRENT_DIR
$1
akan berisi direktori kerja saat ini. (2) The pushd
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.