วิธีรันหนึ่งคำสั่งที่มีไดเรกทอรีเป็นอาร์กิวเมนต์แล้ว cd ไปเหมือนกัน? ฉันได้รับ“ ไม่มีไฟล์หรือไดเรกทอรีดังกล่าว”


15

ฉันต้องการสร้างฟังก์ชั่นสั้น ๆ เพื่อทำสิ่งต่อไปนี้ สมมติว่าฉันย้ายไฟล์ 'file.tex' ไปยังไดเรกทอรีเอกสารของฉัน:

mv file.tex ~/Documents

จากนั้นฉันต้องการไปcdยังไดเรกทอรีนั้น:

cd ~/Documents

ฉันต้องการที่จะพูดคุยนี้ไปยังไดเรกทอรีใด ๆ เพื่อให้ฉันสามารถทำได้:

mv file.tex ~/Documents
follow

และให้followคำสั่งอ่านปลายทางจากคำสั่งก่อนหน้าจากนั้นดำเนินการตามนั้น สำหรับไดเรกทอรีง่าย ๆ มันไม่ได้ประหยัดเวลามาก แต่เมื่อทำงานกับไดเรกทอรีที่ซ้อนกันมันจะยิ่งใหญ่มากที่จะสามารถใช้

mv file.tex ~/Documents/folder1/subfolder1
follow

ฉันคิดว่ามันค่อนข้างง่ายและฉันสามารถทำสิ่งนี้:

follow()
{
    place=`history 2 | sed -n '1p;1q' | rev | cut -d ' ' -f1 | rev`
    cd $place
}

แต่ดูเหมือนว่าจะไม่ทำงาน ถ้าฉันก้อง$placeฉันจะได้รับสตริงที่ต้องการ (ฉันกำลังทดสอบด้วย~/Documents) แต่คำสั่งสุดท้ายกลับมา

No such file or directory

ไดเรกทอรีอยู่แน่นอน ฉันกำลังสูญเสีย คุณช่วยฉันออก


ฉันต้องการจะชี้ให้เห็นว่าถ้าคุณไม่สนใจที่จะfile.texอยู่ในตำแหน่งเดิมsymlinksเป็นทางเลือกที่ดีมากเนื่องจากคุณต้องลิงก์ครั้งเดียวแล้วมันจะชี้ไปที่เวอร์ชันล่าสุดเสมอ
Kroltan

5
วิธีที่ง่ายกว่า: พิมพ์cd alt + .เพื่อแทนที่โทเค็นสุดท้ายของคำสั่งก่อนหน้า ทำซ้ำเพื่อย้อนกลับไปในประวัติศาสตร์ของโทเค็นสุดท้าย (ฉันพูดโทเค็นไม่ได้หาเรื่องเพราะfoo &คว้า&เป็นโทเค็นสุดท้าย) คุณสามารถใช้อาร์กิวเมนต์ที่เป็นตัวเลข (เช่น escape-3 alt +. เป็นต้น)
Peter Cordes


ดูเพิ่มเติมที่mkdir cd combo
Christopher Bottoms

คำตอบ:


18

แทนการกำหนดฟังก์ชั่นที่คุณสามารถใช้ตัวแปรซึ่งจะขยายไปสู่การโต้แย้งสุดท้ายของคำสั่งก่อนหน้าโดย$_ bashดังนั้นใช้:

cd "$_"

หลังจากmvคำสั่ง

คุณสามารถใช้การขยายประวัติได้เช่นกัน:

cd !:$

หากคุณต้องใช้ฟังก์ชั่น:

follow () { cd "$_" ;}

$ follow () { cd "$_" ;}
$ mv foo.sh 'foo bar'
$ follow 
foo bar$ 

หมายเหตุ:คำตอบนี้มีการกำหนดเป้าหมายเป็นรูปแบบอาร์กิวเมนต์บรรทัดคำสั่งที่แน่นอนที่คุณใช้ในขณะที่เรากำลังจัดการกับพารามิเตอร์ตำแหน่ง สำหรับรูปแบบอื่น ๆ เช่นmv -t foo bar.txtคุณจำเป็นต้องรวมการตรวจสอบเฉพาะล่วงหน้าไว้ด้วย


การขยายประวัติของคุณ (cd!: $) ทำงานได้อย่างสมบูรณ์ ขอขอบคุณ. อย่างไรก็ตามอื่น ๆ (cd "$ _") ไม่ได้: mv file.tex ~ / Downloads / cd "$ _" bash: cd: __bp_preexec_invoke_exec: ไม่มีไฟล์หรือไดเรกทอรีดังกล่าวฉันยินดีที่จะยอมรับคำตอบของคุณว่าถูกต้องทั้งหมดและ ขอขอบคุณ.
ไฟ

ฉันได้เสมอพิมพ์ (ค่อนข้างเก้อ) อย่างใดอย่างหนึ่งหรือcd !$ cd $(dirname !$)ไม่ทราบเกี่ยวกับ$_ตัวแปร!
Kalvin Lee

ตอนนี้สิ่งที่เกิดขึ้นถ้าฉันทำmv -t ~/Documents file.texแทนmv file.tex ~/Documents? บรรทัดล่างฉันไม่แน่ใจว่านี่จะแก้ปัญหาได้ในกรณีทั่วไป ... ฟังก์ชั่นเสื้อคลุมรอบหรือ reimplements ที่mvอาจจะดีกว่า ...
CVn

@ MichaelKjörlingจะไม่ทำงานอย่างง่าย ๆ .. ตัวอย่างนี้เป็นเพียงการปกปิดกรณีที่ OP มีไม่ใช่กรณี (หรือทั้งหมด) ..
heemayl

คุณไม่ต้องการลำไส้ใหญ่ !$เทียบเท่า!:$และเร็วกว่าสำหรับการพิมพ์
Wildcard

14

ด้วยปุ่มลัดทุบตีมาตรฐานการรวมกัน Alt.จะคัดลอกอาร์กิวเมนต์สุดท้ายของบรรทัดคำสั่งก่อนหน้าลงในอันปัจจุบัน ดังนั้นการพิมพ์

$ mv foo ~/some/long/path/
$ cd <Alt><.>

จะให้ผลผลิต

$ mv foo ~/some/long/path/
$ cd ~/some/long/path/

followและจะพิมพ์แม้แต่น้อยกว่าคำว่า

เพื่อเพิ่มความสะดวกให้ทำซ้ำ Alt.ชุดจะเรียกดูอาร์กิวเมนต์สุดท้ายของบรรทัดคำสั่งก่อนหน้าทั้งหมด

ภาคผนวก:ชื่อคำสั่งทุบตีสอดคล้องกับคีย์ผสมนี้อยู่หรือyank-last-arg insert-last-argumentสามารถพบได้ใน bash manpage ภายใต้ "คำสั่งสำหรับการจัดการประวัติ" หรือในคู่มืออ้างอิง Bash ที่ละเอียดยิ่งขึ้น)


1
นั่นฉลาด ขอบคุณ! ฉันไม่รู้ว่าสิ่งนี้มีอยู่จริง
ไฟ

@Fire ฉันเพิ่มการอ้างอิงสำหรับคำสั่งเหล่านั้นเพื่อให้คุณสามารถค้นหาการเชื่อมโยงคีย์ที่น่าสนใจมากขึ้น (และลืมพวกเขาอีกครั้งทันทีเช่นฉันทำเสมอ)
Dubu

1
นอกจากนี้คุณยังสามารถใช้<esc>แล้ว.ที่จะได้รับผลเช่นเดียวกับ<alt>+.ที่มีประโยชน์นี้เมื่อคุณมี CapsLock remapped ที่จะหลบหนี :)
gnur

1
ผู้ใช้ @gnur vi (m) ฉันคิดว่า ;-)
Dubu

6

คุณเกือบจะพบปัญหาที่การขยายตัวของตัวหนอนเกิดขึ้นก่อนการขยายตัวพารามิเตอร์ซึ่งสามารถอธิบายได้ด้วยตัวอย่างรวบรัด:

$ cd ~kaz
kaz $ var='~kaz'
kaz $ echo $var
~kaz
kaz $ cd $kaz
bash: cd: ~kaz: No such file or directory

evalนี้สามารถอยู่กับ อย่างไรก็ตามคุณจะต้องการevalเพราะคุณกำลังดึงคำสั่งจากประวัติและพวกเขาสามารถมีการขยายตัวตามอำเภอใจเช่น:

$ mv file.tex ~/Documents/$(compute_folder_name foo-param)/subfolder1
$ follow

(มีปัญหาเช่นว่าการขยายตัวของค่าเหล่านี้อาจไม่ตรงกับการขยายตัวเดิมที่เกิดขึ้นอีกต่อไปสมมติว่าcompute_folder_nameเป็นฟังก์ชั่นที่เพิ่มตัวแปรทั่วโลกบางส่วน)


4
evalคุณไม่จำเป็นต้อง (เคย) แต่สามารถพบปัญหาลำดับการขยายได้ดี หากคุณพูดถึงการขยายประวัติศาสตร์ที่เหมาะสมยิ่งขึ้นในการใช้evalที่นี่นี่จะเป็นคำตอบที่ดีที่สุดในความคิดของฉัน ไม่มีใครอธิบายได้ว่าเหตุใดโซลูชันของโปสเตอร์ต้นฉบับจึงล้มเหลว
Wildcard
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.