ดำเนินการคำสั่งจากไดเรกทอรีอื่นในทุบตี


119

บอกว่าฉันทำสิ่งนี้:

cd subdir
git init
cd ../

มีวิธีการทำเช่นนี้ด้วยคำสั่งเดียวหรืออาจจะสองคนแทนที่จะต้องย้ายเข้าและออกจากไดเรกทอรีเพื่อเรียกใช้คำสั่งที่นั่น?

(ไม่มองหาวิธีแก้ปัญหาเฉพาะ git นั่นเป็นเพียงตัวอย่าง)

คำตอบ:


202

นี่เป็นวิธีที่ดีที่สุด:

( cd dir ; git init )

หรือ

( cd dir && git init )

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


1
และถ้าคุณต้องการตั้งค่าตัวแปรสภาพแวดล้อมหนึ่งหรือสองตัวให้เพิ่มคำสั่งนั้นเป็นคำสั่งอื่นในตอนต้น
ฮิปโป

1
@CraigMcQueen: ไม่ได้จริงๆ $?จะมีรหัสทางออกของคำสั่งสุดท้ายที่ทำงานใน subshell หากคุณใช้&&ตัวแปร (ซึ่งโดยปกติแล้วคุณควรจะ) แล้วคุณจะได้รับรหัสทางออกของคำสั่งแรกที่ล้มเหลว (หรือ 0 ถ้าทุกอย่างตกลง)
Mat

ฉันคิดว่าวงเล็บเป็นตัวเลือก
Francis.Beauchamp

10
@ Francis.Beauchamp: หากคุณละเว้น parens คุณจะอยู่ใน subdir หลังจากคำสั่งแทนที่จะกลับไปที่จุดเริ่มต้น
Mat

วิธีการทำสิ่งนี้บน Windows?
Karl Morrison

22

ฉันกำลังหาวิธีเรียกใช้คำสั่ง git จากพา ธ และทำการเปลี่ยนแปลงที่เก็บในพา ธ อื่น ดังนั้นฉันจึงลงเอยในคำถามนี้ที่นี่

แต่สำหรับความต้องการเฉพาะของฉันทั้งคำตอบที่ได้รับการยอมรับและอื่น ๆ ไม่ได้ช่วย

ฉันต้องการเรียกใช้คำสั่ง git โดยใช้sudo -u USER /usr/bin/git(ผู้ใช้รายอื่นเรียกใช้) และอย่างที่คุณทราบ sudo ไม่อนุญาตให้ฉันเรียกใช้cdคำสั่งดังนั้นฉันไม่สามารถอยู่ในไดเรกทอรีที่เก็บได้

ดังนั้นฉันจึงเดินไปที่หน้าคนของคอมไพล์ และในบรรดาตัวเลือกต่าง ๆ ฉันเห็น--git-dir=<path>:

--git-dir =

ตั้งค่าพา ธ ไปยังที่เก็บ สิ่งนี้สามารถควบคุมได้โดยการตั้งค่าตัวแปรสภาพแวดล้อม GIT_DIR มันสามารถเป็นเส้นทางที่แน่นอนหรือเส้นทางสัมพัทธ์ไปยังไดเรกทอรีการทำงานปัจจุบัน

ดังนั้นถ้ามันช่วยใครซักคนคุณยังสามารถใช้คอมไพล์จากพา ธ และทำการเปลี่ยนแปลงที่เก็บ "ห่างไกลจากคุณ" เพียงใช้:

git --git-dir=/path/to/repository GIT_COMMAND

หรือหากต้องการเรียกใช้ในฐานะผู้ใช้รายอื่นให้ทำดังนี้:

echo USER_PASSWORD | sudo -u USER_LOGIN -S /usr/bin/git --git-dir=/path/to/repository GIT_COMMAND

รวมทั้งจากหน้าคนของ git-init :

หากตัวแปรสภาพแวดล้อม $ GIT_DIR ถูกตั้งค่ามันจะระบุพา ธ ที่จะใช้แทน. /.git สำหรับฐานของที่เก็บ

ดังนั้นหากคุณต้องการเริ่มต้นพื้นที่เก็บข้อมูลภายใต้โฟลเดอร์. git ปกติคุณจะต้องระบุพร้อมกับ--git-dirตัวเลือก เช่น:

echo USER_PASSWORD | sudo -u USER_LOGIN -S /usr/bin/git --git-dir=/path/to/repository/.git init

หลังจากเริ่มต้นพื้นที่เก็บข้อมูลบน/path/to/repo/.gitคำสั่งเพิ่มเติมทั้งหมดควรมีตัวเลือก--work-tree=<path>ตามที่อธิบายไว้ในหน้าคนของ git:

--work ต้นไม้ =

กำหนดเส้นทางไปยังแผนผังการทำงาน สามารถเป็นพา ธ สัมบูรณ์หรือพา ธ ที่สัมพันธ์กับไดเร็กทอรีการทำงานปัจจุบัน สิ่งนี้สามารถควบคุมได้โดยการตั้งค่าตัวแปรสภาพแวดล้อม GIT_WORK_TREE และตัวแปรการกำหนดค่า core.worktree (ดูที่ core.worktree ใน git-config (1) สำหรับการสนทนาที่ละเอียดยิ่งขึ้น)

ดังนั้นคำสั่งที่ถูกต้องในการรัน git ในฐานะผู้ใช้รายอื่นและเริ่มต้นพื้นที่เก็บข้อมูลใหม่คือ:

echo USER_PASSWORD | sudo -u USER_LOGIN -S /usr/bin/git --git-dir=/path/to/repository/.git init
echo USER_PASSWORD | sudo -u USER_LOGIN -S /usr/bin/git --git-dir='/path/to/repository/.git' --work-tree='/path/to/repository' add /path/to/repository/*
echo USER_PASSWORD | sudo -u USER_LOGIN -S /usr/bin/git --git-dir='/path/to/repository/.git' --work-tree='/path/to/repository' commit -m 'MESSAGE'
echo USER_PASSWORD | sudo -u USER_LOGIN -S /usr/bin/git --git-dir='/path/to/repository/.git' --work-tree='/path/to/repository' remote add origin user@domain.com:path
echo USER_PASSWORD | sudo -u USER_LOGIN -S /usr/bin/git --git-dir='/path/to/repository/.git' --work-tree='/path/to/repository' push -u origin master

หากคุณใช้ sudo แบบโต้ตอบและไม่ผ่านสคริปต์คุณสามารถทำได้sudo -iหรือsudo suรับรูทเชลล์แบบโต้ตอบ
Bugster

ฉันนึกไม่ออกว่าทำไมถึง( cd subdir && sudo -u USER /usr/bin/git init )ไม่ทำงาน
สกอตต์

เกิดอะไรขึ้นถ้าผมไม่ได้รับอนุญาตให้เข้าถึงsubdir?
dmmd

13

ไม่ใช่สิ่งที่คุณกำลังถาม (คุณมีคำตอบจริงด้านบนพร้อมกับ subshell) แต่ดูpushdและpopd


ฉันลองกับ cd && สำหรับ maven และมันใช้งานไม่ได้ แต่ pushd และ popd ทำงานได้อย่างสมบูรณ์แบบ ขอบคุณ
Radu Toader

6

คุณมีตัวเลือกน้อย คุณสามารถกลุ่มคำสั่งด้วยหรือ&& ;แบบนี้:

cd subdir && git init && cd ..

หรือ

cd subdir; git init; cd ..

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

อีกตัวเลือกหนึ่งคือการกำหนดฟังก์ชั่นและใช้งานเช่น:

function cdinit() {
    cd $1
    git init
    cd ..
}

จากนั้นคุณสามารถเรียกใช้คำสั่ง:

cdinit subdir

และมันจะgit initอยู่ในไดเรกทอรีนั้นโดยอัตโนมัติและย้ายออกจากมัน

คุณสามารถแก้ปัญหาที่ซับซ้อนมากขึ้นโดยใช้ฟังก์ชั่นหากคุณมีไดเรกทอรีจำนวนมากและต้องการgit initใช้คำสั่งเดียว

function cdinit() {
    for arg in $@
    do
        cd $arg
        git init
        cd ..
    done
}

จากนั้นคุณสามารถเรียกใช้สิ่งนี้ด้วย:

cdinit subdir1 subdir2 subdir3

และจะทำgit initในsubdir1, และsubdir2subdir3


ขอบคุณ ฉันรู้&&และ;หวังว่าจะได้สิ่งที่สวยงามกว่านี้ เสียงเหมือนเขียนสคริปต์เป็นตัวเลือกที่ดีที่สุดของฉัน
เทรเวอร์เบิร์นแฮม

การแก้ไข: คำตอบนี้ใช้ได้ แต่คำตอบของ Mat นั้นดีกว่าสำหรับความต้องการเฉพาะของฉัน
เทรเวอร์เบิร์นแฮม

คุณคิดว่าcdinitฟังก์ชั่นของคุณสามารถวางนัยสำหรับคำสั่งโดยพลการหรือไม่? ฉันพยายามใช้เพียงข้อโต้แย้ง แต่ก็ไม่ได้ผล
Chetan Bhasin

(1) นิวไลน์เทียบเท่ากับเพื่อให้ฟังก์ชั่นสามบรรทัดเทียบเท่ากับ; cd $1; git init; cd ..(2) คุณควรพูดตัวแปรของคุณ: "$1", และ"$@" "$arg"หรือคุณสามารถย่อไปfor arg in "$@" for arg
สกอตต์

5

ในกรณีของgit(อย่างน้อยในรุ่น 2.7.0) คุณสามารถใช้ประโยชน์จาก-Cตัวเลือกที่ทำให้คอมไพล์ทำงานเหมือนว่ามันเริ่มต้นในไดเรกทอรีที่กำหนด ดังนั้นโซลูชันของคุณอาจมีลักษณะดังนี้:

> git -C subdir init
Initialized empty Git repository in /some/path/subdir/.git/

การอ้างถึงเอกสาร:

Run as if git was started in <path> instead of the current working directory. When multiple -C options are given, each subsequent non-absolute -C
<path> is interpreted relative to the preceding -C <path>.

This option affects options that expect path name like --git-dir and --work-tree in that their interpretations of the path names would be made
relative to the working directory caused by the -C option. 

2

คุณสามารถจัดกลุ่มคำสั่งด้วย && เช่น

cd subdir && git init && cd ../

หากคุณไม่ต้องการการพึ่งพาใด ๆ กับโค้ดทางออกของแต่ละคำสั่งคุณสามารถใช้; แทนคือ:

cd subdir ; git init ; cd ../

1
หรือด้วยวิธีการ;ที่พวกเขาไม่ได้ขึ้นอยู่กับรหัสส่งคืนของก่อนหน้านี้
slhck

(1)  cd subdir && git init ; cd ..จริง ๆ แล้วอาจจะสมเหตุสมผลที่สุด หากผู้ใช้ต้องการเรียกใช้git initคำสั่งในsubdirนั้นพวกเขาอาจไม่ต้องการเรียกใช้คำสั่งในไดเรกทอรีปัจจุบัน นั่นคือพวกเขาไม่ต้องการเรียกใช้หาก (ครั้งแรก) cdล้มเหลว (ถึงแม้ว่ามันจะเป็นไปได้ที่ความ  cdล้มเหลวเพราะเราอยู่ในsubdirนั้น แต่เป็นกรณีมุม) ... (ต่อ)
สกอตต์

(ต่อ) ... อย่างไรก็ตามหากผู้ใช้ต้องการจัดการบล็อกของสามคำสั่งเป็นหน่วยพวกเขาอาจต้องการ  cdสำรองข้อมูลไปยังไดเรกทอรีเริ่มต้นแม้ว่าgit initคำสั่งจะล้มเหลว ( หรือพวกเขาอาจต้องการที่จะอยู่ในไดเรกทอรีย่อยและวินิจฉัยความล้มเหลวคำสั่ง.) (2) คุณไม่จำเป็นที่จะรวมหลัง/..
สกอตต์

2

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

แต่คุณสามารถเขียนสคริปต์ทุบตีที่ใช้ไดเรกทอรีเป้าหมายและคำสั่งเป็นพารามิเตอร์ สำหรับสิ่งนี้คุณสามารถดู pushd และ popd: http://ss64.com/bash/pushd.html

ฉันจะเขียนสคริปต์เล็กน้อยสำหรับคุณ แต่ฉันไม่มีกล่อง Linux ที่นี่ :)


เพิ่งเห็นคำตอบจาก Mark Szymanski คุณสามารถใช้พารามิเตอร์ที่สองสำหรับคำสั่ง (และเปลี่ยนชื่อคำสั่ง) และคุณมีสิ่งที่คุณต้องการ
wullxz

1

โปรแกรมมีวิธีจัดการอาร์กิวเมนต์ที่แตกต่างกันดังนั้นบางรายการจะมีตัวเลือก-folder = ชื่อเทียบเท่า นอกเหนือจากข้อยกเว้นนั้นมาตรฐานแม้ใน MS DOS ก็เป็นเพียง

$ โปรแกรม subdir

บางครั้งคุณต้องการ

$ โปรแกรมย่อย /

โปรแกรมจะเปิดโฟลเดอร์ทำงานด้วยวิธีเดียวกับที่คุณทำงานกับไฟล์และเมื่อเสร็จแล้วให้ส่งคืนการควบคุมเชลล์ของคุณซึ่งชี้ไปที่ไดเรกทอรีมาตรฐานดั้งเดิมของคุณ โปรแกรมที่จัดการด้วยวิธีนี้จะมีปัญหาที่เอาต์พุตข้อผิดพลาด (เช่น core dumps) ไปที่ไฟล์ในไดเรกทอรีปัจจุบันของเชลล์ (แทนที่จะเป็นsubdir )

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

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