วิธีการเรียกใช้นามแฝงในเชลล์สคริปต์?


101

ฉันมีแฟ้มที่ปฏิบัติการซึ่งเป็นเส้นทางแบบเต็มmpiexec ~/petsc-3.2-p6/petsc-arch/bin/mpiexecเนื่องจากฉันต้องการรันคำสั่งนี้ในไดเรกทอรีต่าง ๆ (โดยไม่ต้องพิมพ์เส้นทางทั้งหมด) ฉันจึงตั้งค่านามแฝงใน.bashrcไฟล์โฮมของฉัน:

alias petsc="~/petsc-3.2-p6/petsc-arch/bin/mpiexec"  

ซึ่งทำให้ฉันสามารถรันmpiexecไฟล์นี้ที่ command prompt ได้อย่างง่ายดายโดยพิมพ์:

petsc myexecutable

ฉันพยายามเขียนไฟล์สคริปต์เชลล์ชื่อscriptใช้นามแฝงใหม่petscเป็นคำสั่ง หลังจากให้สิทธิ์สคริปต์เชลล์ของฉัน (โดยใช้chmod) ฉันพยายามเรียกใช้สคริปต์ อย่างไรก็ตามมันทำให้ฉันมีข้อผิดพลาดต่อไปนี้:

./script: line 1: petsc: command not found

ฉันรู้ว่าฉันสามารถเขียนพา ธ แบบเต็มไปยังmpiexecไฟล์ได้ แต่มันก็ยุ่งยากในการเขียนพา ธ แบบเต็มทุกครั้งที่ฉันต้องการเขียนสคริปต์ใหม่ มีวิธีที่ฉันสามารถใช้นามแฝงpetscในไฟล์สคริปต์หรือไม่? มีวิธีที่ฉันสามารถแก้ไข.bashrcหรือ.bash_profileทำให้เกิดขึ้นได้หรือไม่


วิธีการเกี่ยวกับการเพิ่มนามแฝงไปที่.bash_aliases? นอกจากนี้วิธีการเกี่ยวกับนามแฝงเส้นทางที่แน่นอนแทนเส้นทางญาติเช่นalias petsc='/home/user/petsc-3.2-p6/petsc-arch/bin/mpiexec'
Nitin Venkatesh

@nitstorm: วิธีแก้ปัญหาทั้งดูเหมือนว่าจะไม่ทำงาน ... ฉันยังคงได้รับข้อผิดพลาดเหมือนเดิม
พอล

ที่เกี่ยวข้อง: unix.stackexchange.com/questions/1496/…
AlikElzin-kilaka

คำตอบ:


74
  1. ในเชลล์สคริปต์ของคุณใช้เส้นทางแบบเต็มแทนที่จะเป็นนามแฝง

  2. ในเชลล์สคริปต์ของคุณตั้งค่าตัวแปรไวยากรณ์ที่แตกต่าง

    petsc='/home/your_user/petsc-3.2-p6/petsc-arch/bin/mpiexec'
    
    $petsc myexecutable
  3. ใช้ฟังก์ชั่นในสคริปต์ของคุณ น่าจะดีกว่าถ้าpetscมีความซับซ้อน

    function petsc () {
        command 1
        command 2
    }
    
    petsc myexecutable
  4. ระบุชื่อแทนของคุณ

    shopt -s expand_aliases
    source /home/your_user/.bashrc

คุณอาจไม่ต้องการแหล่งที่มาของคุณ.bashrcดังนั้น IMO หนึ่งในสามอันดับแรกจะดีกว่า


16
จุดที่ 4 ไม่ทำงานยกเว้นว่าคุณใช้shopt -s expand_aliasesในสคริปต์เดียวกัน
enzotib

ข้อเสนอแนะของคุณ 2) ใช้งานได้ แต่ฉันต้องการที่จะใช้คำสั่งเดียวกันในหลาย ๆ เชลล์สคริปต์โดยไม่ต้องเขียนบรรทัดแรก Petsc = "... " มีวิธีทำเช่นนี้หรือไม่?
เปาโล

1
@enzotib - ขอบคุณฉันเพิ่มที่คำตอบของฉัน
Panther

1
ในจุดที่ 2 คุณไม่ได้ตั้งค่านามแฝง แต่เป็นตัวแปร
pabouk

1
ไม่ได้ถามโดย OP แต่เกี่ยวข้องกับชื่อคำถาม: 2 |จุดจะไม่ทำงานกับคำสั่งที่มี ที่นี่ใช้shopt -s expand_aliasesนามแฝงและท้องถิ่นเช่นalias myalias='echo abc|rev'- ต้องมีการแบ่งบรรทัดก่อนการใช้งาน (ดู ALIASES ในman bash) จุดที่ 4: ไฟล์ที่มาอาจป้องกันไม่ให้มีการดำเนินการที่ไม่ใช่แบบโต้ตอบเช่นในสคริปต์ มองหาในช่วงต้นexitหรือreturnเช่น[ -z "$PS1" ] && return(ตรวจสอบว่าไม่ได้ตั้งค่าพรอมต์หลักที่ระบุว่าไม่ใช่เชลล์แบบโต้ตอบ) หรืออาจมีการตรวจสอบiใน$-( $-มีตัวเลือกเชลล์iหมายถึงแบบโต้ตอบ) ดูman bashตัวแปรเหล่านั้น
ใช้ได้

61

นามแฝงจะเลิกในความโปรดปรานของฟังก์ชั่นเปลือก จากbashหน้าคู่มือ:

For almost every purpose, aliases are superseded by shell functions.

ในการสร้างฟังก์ชั่นและส่งออกไปยัง subshells ให้ใส่สิ่งต่อไปนี้ใน~/.bashrc:

petsc() {
    ~/petsc-3.2-p6/petsc-arch/bin/mpiexec "$@"
}
export -f petsc

จากนั้นคุณสามารถเรียกคำสั่งของคุณได้อย่างอิสระจากสคริปต์ของคุณ


เกือบจะใช้งานได้ ... ปัญหาเดียวคือฉันต้องสามารถส่งค่าสถานะที่แตกต่างไปยัง "mpiexec" ที่ปฏิบัติการได้ ... ตัวอย่างเช่นฉันต้องสามารถดำเนินการบางอย่างเช่น "Petsc -n 40 myexecutable" ด้วย นามแฝง "petsc"
พอล

4
@ พอล: ฉันเพิ่ม"$@"เพียงเพื่อจัดการกับข้อโต้แย้ง
enzotib

12

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

  • (หากคุณไม่ต้องการใช้mpiexecแทนpetsc) เพิ่ม$HOME/petsc-3.2-p6/petsc-arch/binในPATHตัวแปรของคุณ สามารถทำได้โดยการแก้ไข~/.profileและต่อท้าย:

    PATH="$HOME/petsc-3.2-p6/petsc-arch/bin:$PATH"

    ลงชื่อเข้าใช้อีกครั้งเพื่อใช้การเปลี่ยนแปลงเหล่านี้

  • สร้างไดเรกทอรี~/binและ

    • ทำสคริปต์ wrapper ชื่อpetscประกอบด้วย:

      #!/bin/sh
      exec ~/petsc-3.2-p6/petsc-arch/bin/mpiexec "$@"
    • หากโปรแกรมอนุญาตให้ทำได้คุณสามารถข้าม shellscript และสร้าง symlink โดยใช้คำสั่ง:

      ln -s ~/petsc-3.2-p6/petsc-arch/bin/mpiexec ~/bin/petsc

9

ใน bash 4 คุณสามารถใช้ตัวแปรพิเศษ: $BASH_ALIASES.

ตัวอย่างเช่น:

$ alias foo="echo test"
$ echo ${BASH_ALIASES[foo]}
echo test
$ echo `${BASH_ALIASES[foo]}` bar
test bar

evalอีกวิธีหนึ่งคือกำหนดเป็นตัวแปรแล้วใช้แทนคำสั่งหรือ

ตัวอย่างเช่นแทนที่จะกำหนดนามแฝงเช่น:

alias foo="echo test"

กำหนดเป็น:

foo="echo test"

แทน. จากนั้นดำเนินการโดย:

find . -type f -exec sh -c "eval $foo" \;

หรือ:

find . -type f -exec sh -c "echo `$foo`" \;

นามแฝง Altough ถูกคัดค้านฟังก์ชันเชลล์คำตอบนี้เป็นเพียงคำตอบเดียวที่ควรได้รับการยอมรับ แม้แต่ Debian 8 รุ่นเก่าก็มี bash เวอร์ชัน 4 ดังนั้นจึง${BASH_ALIASES[alias]}เป็นตัวเลือกที่ดี ไม่เช่นนั้นฉันต้องแก้ไขบรรทัด. bash_aliases จำนวนมากเพื่อใช้งานอื่น ๆ ขอขอบคุณ.
erm3nda

8

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

ตัวอย่าง:

~ $ grep ll .bashrc
alias ll='ls -lah'
~ $ cat script.sh 
#!/bin/sh

ll
~ $ bash script.sh 
script.sh: line 3: ll: command not found
~ $ bash -i script.sh
..directory contents..

ข้อมูลเพิ่มเติม:

$ man bash

2
.bashrcนอกจากนี้ยังมีการอ่านคำสั่งในระหว่างการดำเนิน SSH ไม่โต้ตอบ (ที่ว่าทำไมมันมีการตรวจสอบการติดต่อสื่อสารที่ด้านบน)
Muru

6
ALIASES
   ...
   Aliases are not expanded when the shell is not interactive, unless the expand_aliases shell option is set using shopt (see the description of shopt under SHELL BUILTIN COMMANDS
   below).

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

#!/bin/bash

shopt -s expand_aliases

alias foo=bar

foo whatever

สำหรับสาเหตุที่ฉันต้องการทำสิ่งนี้: เนื่องจากสถานการณ์ที่ผิดปกติฉันต้องหลอกให้ Dockerfile คิดว่าเป็นเชลล์สคริปต์


4
  1. ใน.bash_aliases:

    petsc {
    ~/petsc-3.2-p6/petsc-arch/bin/mpiexec "$@"
    }

    .bashrcหรือใส่ฟังก์ชั่นใน โดยปกติแล้วจะเก็บไว้ใน.bashrcการตั้งค่า config เท่านั้นbash

  2. ในอาคารผู้โดยสาร: source .bash_aliases

  3. เรียกมันว่า: petsc arg(s)

ประโยชน์: คุณไม่จำเป็นต้องอยู่ในexport -f petsc .bash_aliasesนามแฝงเลิกใช้แล้ว แต่ใช้.bash_aliasesสำหรับฟังก์ชั่นก็โอเค


ฉันชอบวิธีนี้ฉันจะลองอีกครั้งในภายหลัง
Greenonline

2
  1. ใช้นามแฝงในเชลล์สคริปต์ของคุณ
  2. แหล่งสคริปต์ของคุณในปัจจุบันเปลือกโต้ตอบของคุณแทนการดำเนินการ

ดังนั้นหากคุณมีไฟล์ที่เรียกว่าscript.shคำสั่งของคุณซึ่งรวมถึงการใช้นามแฝงให้พิมพ์:

source script.sh

@DavidFoerster วิธีนี้ใช้งานได้ดี การจัดหาสคริปต์ด้วย.หรือsourcebuiiltin ทำให้เชลล์ปัจจุบันดำเนินการคำสั่งทั้งหมดที่อยู่ในนั้น หากการขยายนามแฝงจะเกิดขึ้นในเชลล์ที่รัน.หรือsourceรันอยู่มันจะเกิดขึ้น อย่างไรก็ตามสิ่งสำคัญคือต้องตระหนักว่าวิธีนี้บางครั้งก็มีประโยชน์เพราะบ่อยครั้งที่หนึ่งต้องการหรือต้องการรันสคริปต์ในเชลล์ของตัวเองด้วยสภาพแวดล้อมของตัวเอง เชลล์สคริปที่เขียนด้วยความตั้งใจที่จะถูกดำเนินการตามปกติไม่ควรจะมาจากแหล่งที่มาแทน - พวกเขามักจะทำงานไม่ถูกต้อง
Eliah Kagan

@EliahKagan: ขอบคุณ ตอนนี้ฉันเข้าใจสิ่งที่คำตอบควรจะหมายถึง ฉันจะเพิ่มคำอธิบาย
David Foerster

1

(แก้ไข: ฟังก์ชั่นที่ลบออกเนื่องจากฉันอ่านผิดการเรียกใช้ mpiexec)

หากสิ่งเดียวที่คุณต้องการคือการพิมพ์น้อยทำไมคุณไม่ใส่โฟลเดอร์ไว้ใน $ PATH? หรือทำ symlink เพื่อ mpiexec จากบางโฟลเดอร์ใน $ PATH? หรือ (โปรด) ใส่ชื่อแทนไว้ในสคริปต์ที่คุณระบุไว้ในสคริปต์การโทร


1
เหตุผลที่ฉันไม่สามารถใส่ลงใน $ PATH ของฉันได้เพราะฉันมีไฟล์ 'mpiexec' อีกอันในไดเรกทอรีอื่นที่มีความสัมพันธ์กันใน $ PATH ของฉัน ถ้าฉันเพิ่มเส้นทางไปยัง 'mpiexec' ใหม่นี้มันอาจจะพยายามรันทั้งสองอย่าง ... ใช่ไหม?
เปาโล

1
"$@"ไม่เข้าใจว่าทำไมไม่เพียงแค่ใช้
enzotib

2
พอลมันจะพยายามรันสิ่งที่อยู่ใน PATH ไม่ใช่ทั้งสองอย่าง
unhammer

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