เปลี่ยนไดเรกทอรีปัจจุบันจากสคริปต์ Bash


190

เป็นไปได้ไหมที่จะเปลี่ยนไดเรกทอรีปัจจุบันจากสคริปต์?

ฉันต้องการสร้างโปรแกรมอรรถประโยชน์สำหรับการนำทางไดเรกทอรีใน Bash ฉันสร้างสคริปต์ทดสอบที่มีลักษณะดังนี้:

#!/bin/bash
cd /home/artemb

เมื่อฉันรันสคริปต์จาก Bash shell ไดเรกทอรีปัจจุบันจะไม่เปลี่ยนแปลง เป็นไปได้หรือไม่ที่จะเปลี่ยนไดเรกทอรีเชลล์ปัจจุบันจากสคริปต์?


2
เพียงแค่ข้อเสนอแนะการเพิ่มประสิทธิภาพ: ถ้าคุณใช้pushd(อาจจะเปลี่ยนเส้นทางไปยัง>/dev/nullที่จะระงับการส่งออก) แทนภายหลังคุณสามารถกลับไปยังไดเรกทอรีก่อนหน้านี้มีcd popd
mklement0

ความเป็นไปได้ที่ซ้ำกันของเหตุใด "cd" จึงไม่ทำงานในสคริปต์เชลล์ bash
Roland

คำตอบ:


173

คุณต้องแปลงสคริปต์เป็นฟังก์ชันเชลล์:

#!/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
}

เหตุผลก็คือแต่ละกระบวนการมีไดเรกทอรีปัจจุบันของตัวเองและเมื่อคุณรันโปรแกรมจากเชลล์มันจะทำงานในกระบวนการใหม่ "cd" มาตรฐาน "pushd" และ "popd" ถูกสร้างขึ้นในตัวแปลเชลล์เพื่อให้มีผลต่อกระบวนการเชลล์

โดยการทำให้โปรแกรมของคุณเป็นฟังก์ชันของเชลล์คุณกำลังเพิ่มคำสั่งในกระบวนการของคุณเองจากนั้นการเปลี่ยนแปลงไดเรกทอรีใด ๆ จะได้รับการสะท้อนในกระบวนการเชลล์


2
คุณจะทำสิ่งนี้ใน tcsh ได้อย่างไร
joedborg

4
+1 สิ่งหนึ่งที่ฉันสังเกตเห็นคือในไฟล์เราต้องกำหนดฟังก์ชั่นก่อนที่จะเรียกมัน มันอาจช่วยคนที่ไม่มีประสบการณ์เหมือนฉัน
Bhushan

อะไรคือความแตกต่างระหว่างการกำหนดฟังก์ชั่นและการสร้างนามแฝง
HelloGoodbye

1
เมื่อฉันสร้างไฟล์ myprog.sh แล้วเพิ่มลงใน. bashrc ฉันจะรันสคริปต์ได้อย่างไร ฉันควรจะเรียกใช้ฟังก์ชั่นของฉันจากไฟล์เปลือกอื่นหรือโดยตรงจากเปลือก? ดูเหมือนว่ามันจะใช้งานไม่ได้ทั้งวิธี ...
Andrea Silvestri

1
@AndreaSilvestri ทั้งออกจากระบบและกลับเข้าสู่ระบบหรือแหล่ง. bashrc การเพิ่มลงใน. bashrc จะไม่ทำอะไรเลยจนกว่าจะมีการเรียกใช้
Jon Strayer

214

เมื่อคุณเริ่มต้นสคริปต์กระบวนการใหม่จะถูกสร้างขึ้นที่สืบทอดสภาพแวดล้อมของคุณเท่านั้น เมื่อมันสิ้นสุดลงก็จะสิ้นสุดลง สภาพแวดล้อมปัจจุบันของคุณยังคงเหมือนเดิม

คุณสามารถเริ่มต้นสคริปต์ของคุณดังนี้:

. myscript.sh

.จะประเมินสคริปต์ในสภาพแวดล้อมปัจจุบันดังนั้นจึงอาจจะมีการเปลี่ยนแปลง


4
+1 เพราะคุณพูดถูก แม้ว่าฉันจะสงสัยอย่างจริงใจว่าเขาจะต้องการให้แหล่งที่มาเปลี่ยนสคริปต์ทุกครั้งที่เขาต้องการมัน ยิ่งไปกว่านั้น.shส่วนขยายต่างๆนั้นมี eww ทั้งหมด อย่าใช้มัน
lununath

1
ใช่โดยปกติจะเป็นการดีกว่าที่จะไม่ใช้วิธีนี้ ส่วนใหญ่คุณจะดีใจที่สภาพแวดล้อมปัจจุบันของคุณไม่ประสบ แต่แล้วฉันก็มีสคริปต์เพื่อทำงานการตั้งค่าบางอย่างสำหรับฉันรวมถึงการเปลี่ยนสถานที่ที่เหมาะสมและจากนั้นฉัน พวกเขาด้วย Btw แน่นอนว่าเป็นเรื่องของความเป็นส่วนตัว ฉันอาจจะไม่ใช้มันในขณะที่ติดตั้งระบบสคริปต์ทั้งหมด แต่ในของฉัน ~ / bin ผมใช้พวกเขาจะรู้ว่าอะไรคือสิ่งที่ :)
Norbert Hartl

11
@ lhunath ทำไมนามสกุล. sh ทั้งหมด eww
Carl Pritchett

1
@CarlPritchett CommandName ส่วนขยายพิจารณาอันตราย
gniourf_gniourf

1
สำหรับฉันแล้วการให้เหตุผลในบทความนั้นเป็นการหลอกลวง ดูเหมือนว่าผลลัพธ์จะได้รับการทราบล่วงหน้า แต่การหาเหตุผลว่าไม่ใช่เรื่องง่าย ดังนั้นฉันจึงยืนประเด็นของฉันมันเป็นเรื่องของสไตล์ส่วนตัวไม่มีอะไรอื่น
Norbert Hartl

55

ในแง่ของความไม่สามารถอ่านได้และการตอบโจทย์ที่มากเกินไปผมเชื่อว่านี่คือสิ่งที่ผู้ร้องขอควรทำ

  1. เพิ่มสคริปต์นั้นลงใน PATH
  2. เรียกใช้สคริปต์เป็น . scriptname

.(dot) จะให้แน่ใจว่าสคริปต์ที่ไม่ได้ทำงานในเปลือกเด็ก


38

การใส่ด้านบนเข้าด้วยกันคุณสามารถสร้างนามแฝง

alias your_cmd=". your_cmd"

ถ้าคุณไม่ต้องการเขียนผู้นำ "" ทุกครั้งที่คุณต้องการแหล่งสคริปต์ของคุณไปยังสภาพแวดล้อมของเชลล์หรือถ้าคุณไม่ต้องการที่จะจำว่าต้องทำเพื่อให้สคริปต์ทำงานได้อย่างถูกต้อง


การพักนี้จะคงอยู่ตลอดการบู๊ตใหม่หรือไม่
SDsolar

1
@SDsolar คุณต้องเพิ่มไฟล์นี้ลงในไฟล์ ~ / .bashrc ของคุณเพื่อให้คงอยู่ ทำงานเหมือนจับใจสำหรับฉัน
Rafał G.

สามารถใส่ใน ~ / .bash_aliases
Champ

@Champ ~/.bash_aliasesไม่ได้มีที่มาเสมอเมื่อเปิดใช้ Bash
Mateusz Piotrowski

31

หากคุณกำลังใช้ bash คุณสามารถลองใช้ alias:

ลงในไฟล์. bashrc เพิ่มบรรทัดนี้:

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

เมื่อคุณเขียน "p" บนบรรทัดคำสั่งมันจะเปลี่ยนไดเรกทอรี


1
+1 สำหรับนามแฝง ฟังก์ชั่นเชลล์น่าสนใจ แต่ OP ขอให้ใช้ nav อย่างง่ายพร้อม cd ฉันเดาว่าคนส่วนใหญ่ต้องการสคริปต์แบบนี้เพื่อนำทางสาขาซอร์สโค้ดและสำหรับนามแฝงนั้นก็เพียงพอแล้ว
Brad Dre

19

หากคุณเรียกใช้สคริปต์ทุบตีมันจะทำงานในสภาพแวดล้อมปัจจุบันหรือบนลูก ๆ ของมันอย่าอยู่บนพาเรนต์

หากเป้าหมายคือการเรียกใช้คำสั่งของคุณ: goto.sh / home / test จากนั้นทำงานแบบโต้ตอบใน / home / test วิธีหนึ่งคือการใช้เชลล์ย่อยแบบโต้ตอบ bash ภายในสคริปต์ของคุณ:

#!/bin/bash
cd $1
exec bash

วิธีนี้คุณจะอยู่ใน / home / test จนกว่าคุณจะออก (exit หรือ Ctrl + C) ของเชลล์นี้


ฉันคิดว่าสิ่งนี้จะแก้ไขปัญหาสำหรับเชลล์สคริปต์ที่ฉันใช้ แต่มันเริ่มต้นเชลล์และลืมสิ่งที่ฉันต้องการ
vwvan

14

ด้วยpushdไดเร็กทอรีปัจจุบันจะถูกพุชบนไดเร็กทอรีสแต็กและถูกเปลี่ยนเป็นไดเร็กทอรีที่กำหนดpopdจะรับไดเร็กทอรีที่อยู่ด้านบนของสแต็กและเปลี่ยนจากนั้นเป็นไดเร็กทอรีนั้น

pushd ../new/dir > /dev/null
# do something in ../new/dir
popd > /dev/null

2
นี่ตอบคำถามของฉัน - ปรับใช้โซลูชันนี้ด้วยสคริปต์ S3 init และทำงานได้ดีอย่างสมบูรณ์ ขอบคุณ @seb
19h

5

เพียงไปที่

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

และเพิ่มรหัสนี้ถัดจากบรรทัดสุดท้าย:

alias yourcommand="cd /the_path_you_wish"

จากนั้นออกจากเครื่องมือแก้ไข

จากนั้นพิมพ์:

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

ตอนนี้คุณสามารถใช้: คำสั่งของคุณใน terminal



3

โดยทั่วไปเราใช้cd..เพื่อกลับมาจากทุกไดเรกทอรี ฉันคิดว่าจะทำให้ง่ายขึ้นโดยกำหนดจำนวนไดเรกทอรีที่คุณต้องการกลับมาอีกครั้ง คุณสามารถใช้สิ่งนี้โดยใช้ไฟล์สคริปต์แยกโดยใช้คำสั่ง alias ตัวอย่างเช่น:

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'   

หลังจากใช้source code.shในเชลล์ปัจจุบันคุณสามารถใช้:

$back 2 

เพื่อกลับมาสองขั้นตอนจากไดเรกทอรีปัจจุบัน อธิบายในรายละเอียดมากกว่าที่นี่ นอกจากนี้ยังมีการอธิบายวิธีการใส่รหัสใน ~ / .bashrc เพื่อให้เชลล์ใหม่ทุกอันที่เปิดอยู่จะมีคำสั่ง alias ใหม่นี้โดยอัตโนมัติ คุณสามารถเพิ่มคำสั่งใหม่เพื่อไปยังไดเรกทอรีที่ต้องการได้โดยการแก้ไขโค้ดโดยเพิ่มif conditionsอาร์กิวเมนต์ที่ต่างกัน นอกจากนี้คุณยังสามารถดึงโค้ดจากคอมไพล์มากกว่าที่นี่


วิธีแก้ปัญหาที่ดีดังนั้นคุณจะไม่ทำให้โปรไฟล์ bash ของคุณ
เสียหาย

0

วิธีนี้ง่ายกว่าสำหรับฉัน

สมมติว่า iMac ส่วนตัวที่คุณเป็นผู้ดูแลระบบอยู่ภายใต้ไดเรกทอรีเริ่มต้นเมื่อเปิดหน้าต่างคำสั่ง / Users / jdoe นี่จะเป็นไดเรกทอรีที่จะไปที่: /Users/jdoe/Desktop/Mongo/db.3.2.1 / bin

นี่คือขั้นตอนที่สามารถทำให้งานสำเร็จได้:

  1. viongobin ที่ฉันป้อน: cd /Users/jdoe/Desktop/Mongo/db.3.2.1/binเป็นบรรทัดแรก
  2. chmod 755 mongobin
  3. source mongobin
  4. pwd

Voila!


0

ฉันยังได้สร้างยูทิลิตีที่ชื่อgoatซึ่งคุณสามารถใช้เพื่อการนำทางที่ง่ายขึ้น

คุณสามารถดูรหัสที่มาบนGitHub

ในฐานะของv2.3.1 ภาพรวมการใช้งานที่มีลักษณะเช่นนี้

# 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

0

ฉันชอบทำสิ่งเดียวกันสำหรับโครงการต่าง ๆ โดยไม่ต้องเริ่มเชลล์ใหม่

ในกรณีของคุณ:

cd /home/artemb

บันทึก the_script เป็น:

echo cd /home/artemb

จากนั้นยิงด้วย:

\`./the_script\`

จากนั้นคุณไปที่ไดเรกทอรีโดยใช้เชลล์เดียวกัน




0

เพียงเขียนPWDและส่งออกภายในสคริปต์ของคุณและการเปลี่ยนแปลงจะยังคงอยู่

export PWD=/your/desired/directory
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.