Ubah direktori saat ini dari skrip Bash

190

Apakah mungkin mengubah direktori saat ini dari skrip?

Saya ingin membuat utilitas untuk navigasi direktori di Bash. Saya telah membuat skrip pengujian yang terlihat seperti berikut:

#!/bin/bash
cd /home/artemb

Ketika saya menjalankan skrip dari Bash shell direktori saat ini tidak berubah. Apakah mungkin untuk mengubah direktori shell saat ini dari skrip?

Artemb
sumber
2
Hanya saran peningkatan: jika Anda menggunakan pushd(mungkin diarahkan >/dev/nulluntuk menekan outputnya) cd, Anda nanti dapat kembali ke direktori sebelumnya popd.
mklement0

Jawaban:

173

Anda perlu mengonversi skrip ke fungsi shell:

#!/bin/bash
#
# this script should not be run directly,
# instead you need to source it from your .bashrc,
# by adding this line:
#   . ~/bin/myprog.sh
#

function myprog() {
  A=$1
  B=$2
  echo "aaa ${A} bbb ${B} ccc"
  cd /proc
}

Alasannya adalah bahwa setiap proses memiliki direktori saat ini sendiri, dan ketika Anda menjalankan suatu program dari shell itu dijalankan dalam proses baru. Standar "cd", "pushd" dan "popd" dibangun pada interpreter shell sehingga memengaruhi proses shell.

Dengan membuat program Anda fungsi shell, Anda menambahkan perintah dalam proses Anda sendiri dan kemudian perubahan direktori tercermin dalam proses shell.

Winden
sumber
2
bagaimana Anda melakukan ini di tcsh?
joedborg
4
+1. Satu hal yang saya perhatikan ada di file, kita harus mendefinisikan fungsi sebelum memanggilnya. Mungkin membantu seseorang yang tidak berpengalaman seperti saya.
Bhushan
Apa perbedaan besar antara mendefinisikan fungsi dan membuat alias?
HelloGoodbye
1
Setelah saya membuat file myprog.sh ini dan menambahkannya ke .bashrc bagaimana saya menjalankan skrip? Haruskah saya memanggil fungsi saya dari file shell lain atau langsung dari shell? Tampaknya itu tidak berhasil dengan cara apa pun ...
Andrea Silvestri
1
@AndreaSilvestri Baik keluar dan masuk kembali atau sumber .bashrc. Menambahkannya ke .bashrc tidak melakukan apa-apa sampai .bashrc dijalankan.
Jon Strayer
214

Saat Anda memulai skrip, proses baru dibuat yang hanya mewarisi lingkungan Anda. Ketika itu berakhir, itu berakhir. Lingkungan Anda saat ini tetap apa adanya.

Sebagai gantinya, Anda dapat memulai skrip Anda seperti ini:

. myscript.sh

The .akan mengevaluasi script dalam lingkungan saat ini, jadi mungkin akan diubah

Norbert Hartl
sumber
4
+1 karena Anda benar. Meskipun saya sungguh-sungguh ragu dia akan ingin sumber skrip direktori berubah setiap kali dia membutuhkannya. Selain itu, .shekstensi benar-benar baru. Jangan gunakan itu.
lhunath
1
Ya, biasanya lebih baik tidak menggunakannya seperti itu. Sebagian besar waktu Anda senang bahwa lingkungan Anda saat ini tidak menderita. Tetapi kemudian saya memiliki skrip untuk melakukan beberapa tugas pengaturan untuk saya termasuk mengubah ke tempat yang tepat dan kemudian saya. mereka juga. Btw. .sh tentu saja masalah gaya pribadi. Saya mungkin tidak akan menggunakannya saat menginstal sistem skrip lebar. Tapi dalam saya ~ / bin saya menggunakan mereka untuk mengetahui apa yang apa :)
Norbert Hartl
11
@ lhunath Mengapa ekstensi .sh benar-benar baru?
Carl Pritchett
1
Ekstensi Commandname @CarlPritchett Dianggap Berbahaya .
gniourf_gniourf
1
Bagi saya alasan dalam artikel itu adalah palsu. Tampaknya hasilnya sudah diketahui sebelumnya tetapi menemukan alasan untuk itu tidak mudah. Jadi saya berpendapat bahwa ini adalah masalah gaya pribadi, bukan yang lain.
Norbert Hartl
55

Mengingat jawaban yang tidak dapat dibaca dan rumit, saya yakin inilah yang harus dilakukan pemohon

  1. tambahkan skrip itu ke PATH
  2. jalankan skrip sebagai . scriptname

The .(dot) akan memastikan script tidak dijalankan di shell anak.

Steven Penny
sumber
38

Menyatukan semua di atas, Anda dapat membuat alias

alias your_cmd=". your_cmd"

jika Anda tidak ingin menulis "." setiap kali Anda ingin sumber skrip Anda ke lingkungan shell, atau jika Anda tidak ingin mengingat itu harus dilakukan agar skrip bekerja dengan benar.

MergerMan
sumber
Apakah ini akan tetap bertahan di seluruh reboot?
SDsolar
1
@SDsolar Anda harus menambahkan ini ke file ~ / .bashrc Anda agar persisten. Bekerja seperti pesona bagi saya.
Rafał G.
Dapat diletakkan di ~ / .bash_aliases
Champ
@ Champ ~/.bash_aliasestidak selalu bersumber saat Bash diluncurkan.
Mateusz Piotrowski
31

Jika Anda menggunakan bash, Anda dapat mencoba alias:

ke dalam file .bashrc tambahkan baris ini:

alias p='cd /home/serdar/my_new_folder/path/'

ketika Anda menulis "p" pada baris perintah, itu akan mengubah direktori.

akarca
sumber
1
+1 untuk alias. fungsi shell menarik tetapi OP meminta nav sederhana dengan cd. Saya kira kebanyakan orang memerlukan skrip seperti ini untuk menavigasi cabang kode sumber dan untuk itu alias sudah cukup
Brad Dre
19

Jika Anda menjalankan skrip bash maka skrip tersebut akan beroperasi pada lingkungannya saat ini atau pada anak-anaknya, tidak pernah pada induknya.

Jika tujuannya adalah untuk menjalankan perintah Anda: goto.sh / home / test Kemudian bekerja secara interaktif di / home / test salah satu cara adalah dengan menjalankan subshell interaktif bash dalam skrip Anda:

#!/bin/bash
cd $1
exec bash

Dengan cara ini Anda akan berada di / home / test sampai Anda keluar (keluar atau Ctrl + C) dari shell ini.

philippe lhardy
sumber
Saya pikir ini akan memperbaiki masalah untuk skrip shell yang saya jalankan tetapi malah memulai shell dan melupakan apa yang saya inginkan.
vwvan
13

Dengan pushd direktori saat ini didorong pada tumpukan direktori dan diubah ke direktori yang diberikan, popd mendapatkan direktori di atas tumpukan dan berubah kemudian ke itu.

pushd ../new/dir > /dev/null
# do something in ../new/dir
popd > /dev/null
seb
sumber
2
Ini menjawab pertanyaan saya - secara aktif menggunakan solusi ini dengan skrip init S3 dan berfungsi dengan baik. Terima kasih @seb.
19h
5

Cukup buka

yourusername/.bashrc (or yourusername/.bash_profile on MAC) by an editor

dan tambahkan kode ini di sebelah baris terakhir:

alias yourcommand="cd /the_path_you_wish"

Kemudian keluar dari editor.

Kemudian ketik:

source ~/.bashrc or source ~/.bash_profile on MAC.

sekarang Anda dapat menggunakan: perintah Anda di terminal

Terima kasih
sumber
3

Pada dasarnya kami gunakan cd..untuk kembali dari setiap direktori. Saya pikir untuk membuatnya lebih mudah dengan memberikan sejumlah direktori yang Anda butuhkan untuk kembali sekaligus. Anda dapat menerapkan ini menggunakan file skrip terpisah menggunakan perintah alias. Sebagai contoh:

code.sh

#!/bin/sh
 _backfunc(){
 if [ "$1" -eq 1 ]; then
  cd ..
 elif [ "$1" -eq 2 ]; then
  cd ../..
 elif [ "$1" -eq 3 ]; then
  cd ../../..
 elif [ "$1" -eq 4 ]; then
  cd ../../../..
 elif ["$1" -eq 10]; then
  cd /home/arun/Documents/work
 fi
 }
alias back='_backfunc'   

Setelah menggunakan source code.shshell saat ini, Anda dapat menggunakan:

$back 2 

untuk kembali dua langkah dari direktori saat ini. Dijelaskan secara rinci di sini . Di sana juga dijelaskan bagaimana memasukkan kode ke ~ / .bashrc sehingga setiap shell yang baru dibuka akan secara otomatis mendapatkan perintah alias baru ini. Anda dapat menambahkan perintah baru untuk pergi ke direktori tertentu dengan memodifikasi kode dengan menambahkan if conditionsargumen yang lebih banyak dan berbeda. Anda juga dapat menarik kode dari git ke sini .

Arun Chettoor
sumber
Solusi yang bagus, sehingga Anda tidak pernah mengacaukan profil bash Anda :)
J4cK
0

Pendekatan ini lebih mudah bagi saya.

Misalkan pada iMac pribadi di mana Anda adalah admin, di bawah direktori default ketika jendela perintah dibuka, / Pengguna / jdoe, ini akan menjadi direktori untuk pergi ke: / Pengguna / jdoe / Dekstop /Mongo/db.3.2.1 /tempat sampah.

Ini adalah langkah-langkah yang dapat menyelesaikan pekerjaan:

  1. vi mongobin, di mana saya masuk: cd /Users/jdoe/Desktop/Mongo/db.3.2.1/binsebagai baris pertama.
  2. chmod 755 mongobin
  3. source mongobin
  4. pwd

Voila!

Daniel C. Deng
sumber
0

Saya juga membuat utilitas bernama goat yang dapat Anda gunakan untuk navigasi yang lebih mudah.

Anda dapat melihat kode sumber di GitHub .

Pada v2.3.1 yang gambaran penggunaan terlihat seperti ini:

# Create a link (h4xdir) to a directory:
goat h4xdir ~/Documents/dev

# Follow a link to change a directory:
cd h4xdir

# Follow a link (and don't stop there!):
cd h4xdir/awesome-project

# Go up the filesystem tree with '...' (same as `cd ../../`):
cd ...

# List all your links:
goat list

# Delete a link (or more):
goat delete h4xdir lojban

# Delete all the links which point to directories with the given prefix:
goat deleteprefix $HOME/Documents

# Delete all saved links:
goat nuke

# Delete broken links:
goat fix
Mateusz Piotrowski
sumber
0

Saya suka melakukan hal yang sama untuk proyek yang berbeda tanpa menyalakan shell baru.

Dalam kasus Anda:

cd /home/artemb

Simpan skrip sebagai:

echo cd /home/artemb

Kemudian jalankan dengan:

\`./the_script\`

Kemudian Anda masuk ke direktori menggunakan shell yang sama.

DrGamma
sumber
0

Tambahkan baris cd di bawah ini di shellscript Anda ini:

exec $SHELL
Alberto Corella
sumber
0

Nyatakan jalur Anda:

PATH='/home/artemb'     
cd ${PATH}
m_sam
sumber
0

Cukup tulis PWDdan ekspor di dalam skrip Anda, dan perubahan akan tetap ada.

export PWD=/your/desired/directory
Samha
sumber