สคริปต์เพื่อเปลี่ยนไดเรกทอรีปัจจุบัน (cd, pwd)


44

ฉันต้องการเรียกใช้สคริปต์เพื่อเปลี่ยนไดเรกทอรีการทำงานปัจจุบัน:

#!/bin/bash
cd web/www/project

แต่หลังจากที่ฉันเรียกใช้แล้ว pwd ปัจจุบันยังคงไม่เปลี่ยนแปลง! ฉันจะทำสิ่งนั้นได้อย่างไร

คำตอบ:


63

มันเป็นพฤติกรรมที่คาดหวังและพูดคุยกันหลายครั้งแล้ว

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

หากต้องการเปลี่ยนไดเรกทอรีอย่างถาวรคุณควรระบุที่มาของสคริปต์ดังเช่น

. ./script

8
@Sony: โปรดทราบว่าคุณควรใช้returnเพื่อหลบหนีจากสคริปต์ที่มาในลักษณะนี้ไม่ใช่exit- พวกเขาเป็นเหมือนฟังก์ชั่นของเชลล์และexitจะออกจากเชลล์ที่มาจากสคริปต์
Charles Stewart

@CharlesStewart ที่จริงแล้วฉันไม่คุ้นเคยกับสคริปต์ที่มา ขอขอบคุณ!
Sony Santos

5
เป็นsource ./scriptเหมือนกันหรือไม่
amyassin

2
@amyassin: ใช่มันเป็น
enzotib

2
1. .และsourceเท่าเทียมกันในการทุบตี 2. เราไม่จำเป็นต้องใช้./ก่อนชื่อไฟล์ถ้ามันอยู่ในไดเรกทอรีเดียวกัน มันก็โอเคที่จะเรียกใช้สิ่งนี้เท่านั้น:. script
sobi3ch

19

สำหรับงานเล็ก ๆ เช่นนี้แทนที่จะสร้างสคริปต์ให้สร้างนามแฝงเช่นนี้

$ alias cdproj='cd /dir/web/www/proj'

คุณควรเพิ่มสิ่งนี้ลงใน.bashrcไฟล์ของคุณหากคุณต้องการให้มันตั้งค่าสำหรับทุกเชลล์แบบโต้ตอบ

$ cdprojตอนนี้คุณสามารถทำงานนี้เป็น


1
นอกจากนี้คุณยังสามารถให้สคริปต์ echo คำสั่งที่จะดำเนินการแล้วใช้eval `./script` หรือeval $(./script)ดำเนินการคำสั่งเหล่านั้น นี่เป็นวิธีการทั่วไปสำหรับคำสั่งที่จำเป็นต้องอัพเดตสภาพแวดล้อมของเชลล์ที่กล่าวอ้าง
Keith Thompson

2
เพียงแค่ระมัดระวังสิ่งที่คุณส่งออกถ้าคุณจะไปevalแนวทาง
jw013

13

ใช้exec bashในตอนท้าย

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

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

หากเป็นกรณีนี้ให้เรียกใช้อินสแตนซ์ bash ของเด็กที่ส่วนท้ายของสคริปต์:

#!/usr/bin/env bash
cd desired/directory
exec bash

สิ่งนี้จะสร้าง subshell ใหม่ พิมพ์exitเพื่อกลับไปที่เชลล์แรกที่สคริปต์เริ่มทำงานในตอนแรก


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

1
เคล็ดลับนี้ใช้ไม่ได้กับเดเบียน 9 ยืด
vdegenne

3
นี่เป็นวิธีที่ผิดที่จะไปเกี่ยวกับเรื่องนี้!
Dennis Williamson

3
เนื่องจากไม่มีใครมีรายละเอียดปัญหาเกี่ยวกับสิ่งนี้ (ฉันกำลังมองคุณ @Dennis): (1) ทุกครั้งที่คุณเรียกใช้มันจะสร้างกระบวนการทุบตีใหม่แบบถาวร ทำสิบหรือยี่สิบครั้งในเซสชั่นและคุณจะมีกระบวนการทุบตี 11 ถึง 21 ซ้อนขึ้น สิ่งนี้อาจส่งผลกระทบต่อประสิทธิภาพการทำงานและหากคุณพยายามที่จะยุติเซสชันอย่างสมบูรณ์โดยการพิมพ์exit(หรือ Ctrl + D) คุณจะต้องทำเช่นนั้น 11 ถึง 21 ครั้ง (2) ข้อเสียเปรียบอีกประการของการใช้สคริปต์ที่เรียกใช้งานได้คือถ้าคุณตั้งค่าตัวเลือกเชลล์ใด ๆ (เช่น  dotglobหรือ  globstar) ในเซสชันเชลล์เชิงโต้ตอบของคุณคุณจะสูญเสียมันเนื่องจากคุณกำลังเริ่มเชลล์ใหม่
G-Man กล่าวว่า 'Reinstate Monica'

1
ทางออกที่ดีมาก! ฉันได้เขียน alias ของฉันใหม่ใน bash_profile ดังนั้นตอนนี้มันเป็นสคริปต์ที่จัดเก็บในไฟล์แยกต่างหาก ฉันใช้สคริปต์เพื่อไปยังโฟลเดอร์ชั่วคราวที่สร้างขึ้นใหม่ และตอนนี้มันง่ายยิ่งขึ้นที่จะมีเซสชัน bash ชั่วคราว กำลังใช้งาน SRP! ขอบคุณ!
artyom.razinov

8

ในขณะที่มีคำตอบที่ดำเนินการอย่างถูกต้องตามที่คุณต้องการวิธีการมาตรฐานที่มากขึ้นสำหรับวัตถุประสงค์ดังกล่าวคือการสร้างลิงก์สัญลักษณ์:

ln -s ~/web/www/project proj   #use full path to dir!

จากนั้นคุณสามารถcdไปที่ไดเรกทอรีโดยใช้ชื่อproj:

cd proj

วิธีนี้มีความยืดหยุ่นมากขึ้นเพราะคุณสามารถเข้าถึงไฟล์โดยใช้ชื่อย่อโดยไม่ต้องcd:

ls proj/   #note the endslash!
vim proj/file.x

4

หากคุณเปลี่ยนระหว่างไดเรกทอรีที่อยู่ในระบบไฟล์ ผมจะแนะนำautojump


4

ขึ้นอยู่กับสิ่งที่คุณกำลังทำวิธีแก้ปัญหาอื่นสามารถสร้างฟังก์ชั่นแทนสคริปต์

ตัวอย่าง:

สร้างฟังก์ชั่นในไฟล์สมมติว่า/home/aidin/my-cd-script:

function my-cd() {
  cd /to/my/path
}

จากนั้นรวมไว้ในbashrcหรือzshrcไฟล์ของคุณ:

# Somewhere in rc file
source /home/aidin/my-cd-script

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

$ my-cd

0

ทำไมไม่ใช้ "exec" มันตะเข็บเพื่อทำสิ่งที่ฉันต้องการ

#!/bin/bash

cd someplace
exec bash

~/someplace

1
ระวังสิ่งที่ดูเหมือนจะเป็นสิ่งที่คุณต้องการ (ม้าไม้ยักษ์! เพียงแค่สิ่งที่ฉันต้องการ!) ทุกครั้งที่คุณเรียกใช้มันจะสร้างกระบวนการทุบตีใหม่แบบถาวร ทำสิบหรือยี่สิบครั้งในเซสชันและคุณจะมีกระบวนการ bash 11 ถึง 21 ครั้งซ้อนกัน สิ่งนี้อาจส่งผลกระทบต่อประสิทธิภาพการทำงานและหากคุณพยายามที่จะยุติเซสชันอย่างสมบูรณ์โดยการพิมพ์exit(หรือ Ctrl + D) คุณจะต้องทำเช่นนั้น 11 ถึง 21 ครั้ง
G-Man กล่าวว่า 'Reinstate Monica'

ฉันสามารถดูได้อย่างแน่นอนว่าจะเป็นปัญหา สำหรับฉันแม้ว่าฉันจะใช้เพียงครั้งเดียวทำงานที่ฉันต้องการแล้วก็ออกไปถ้านั่นเป็นข้อเสียเปรียบเพียงประการเดียวที่ฉันสามารถใช้ชีวิตได้ ในทางกลับกันหากมีทางออกที่ดีกว่าฉันยินดีที่จะดู
paul

คำตอบของ Aidin สำหรับคำถามนี้โดยใช้ฟังก์ชัน shell และคำตอบของ Sachin Divekarโดยใช้ alias นั้นเป็นวิธีที่ดีกว่า (IMO) มากกว่าการใช้สคริปต์ PS ข้อเสียเปรียบอีกประการของการใช้สคริปต์ก็คือถ้าคุณตั้งค่าตัวเลือกเชลล์ใด ๆ (เช่น  dotglobหรือ  globstar) คุณจะสูญเสียมันไปเพราะคุณกำลังเริ่มเชลล์ใหม่ … (ต่อ)
G-Man พูดว่า 'Reinstate Monica'

(ต่อ) … PPS ฉันเพิ่งสังเกตุว่าคุณกำลังย้ำคำตอบของ Serge Stroobandtและพูดว่า '' ทำไมไม่ทำอย่างนี้? '' ที่  Stack Exchangeเราคาดหวังคำตอบที่จะให้ความคิดใหม่และ / หรือข้อมูล คำตอบอื่น ๆ
G-Man กล่าวว่า 'Reinstate Monica'

-1

คุณสามารถทำได้โดยใช้ฟังก์ชั่นหรือการใช้ && ตัวอย่างร้องติดตั้ง Zabbix และสร้างไฟล์ที่มีบรรทัดอยู่ข้างใน

Ex:

#!/bin/bash

# Create Function:
installZabbix(){
    cd /usr/src/zabbix-4.2.4;
    ./configure --enable-agent;
    make install;
    cd /usr/src/;
    >file;
    echo "Hi, this is a file." >>file;
}

# Call the function:
installZabbix

หรือ:

#!/bin/bash
cd /usr/src/zabbix-4.2.4 && ./configure --enable-agent && make install && cd /usr/src && >file && echo "Hi, this is a file." >>file
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.