เพิ่มอาร์กิวเมนต์ให้กับ 'bash -c'


22

สมมติว่าฉันต้องการเรียกใช้คำสั่งผ่าน Bash ดังนี้:

/bin/bash -c "ls -l"

ตามหน้า Bash man ฉันก็สามารถเรียกใช้เช่นนี้:

#               don't process arguments after this one
#               |   pass all unprocessed arguments to command
#               |   |
#               V   V
/bin/bash -c ls -- -l

ยกเว้นดูเหมือนว่าจะไม่ทำงาน (ดูเหมือนจะถูกละเว้น) ฉันกำลังทำอะไรผิดหรือฉันตีความหน้าคนผิดหรือเปล่า?

คำพูดที่เกี่ยวข้องจากมนุษย์:

หากมีอ็อพชัน -c อยู่คำสั่งจะอ่านจากสตริง หากมีข้อโต้แย้งหลังจากสตริงพวกเขาจะถูกกำหนดให้กับพารามิเตอร์ตำแหน่งเริ่มต้นด้วย $ 0

และ

เอ - ส่งสัญญาณการสิ้นสุดของตัวเลือกและปิดการใช้งานการประมวลผลตัวเลือกเพิ่มเติม อาร์กิวเมนต์ใด ๆ หลัง - จะถูกใช้เป็นชื่อไฟล์และอาร์กิวเมนต์

คำตอบ:


33

คุณกำลังตีความหน้าคนผิด ประการแรกส่วนเกี่ยวกับ--การส่งสัญญาณตัวเลือกสุดท้ายนั้นไม่เกี่ยวข้องกับสิ่งที่คุณพยายามทำ -cแทนที่ส่วนที่เหลือของบรรทัดคำสั่งจากจุดนั้นเพื่อที่จะไม่ไปผ่านการจัดการตัวเลือกทุบตีที่ทั้งหมดหมายความว่า--จะถูกส่งผ่านไปยังคำสั่งที่ไม่ได้รับการจัดการโดยทุบตีเป็นจุดสิ้นสุดของเครื่องหมายตัวเลือก

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

/bin/bash -c 'echo "$0" "$1"' foo bar
/bin/bash -c 'echo "$@"' bash foo bar

ในกรณีแรกผ่าน echo พารามิเตอร์$0และ$1อย่างชัดเจนและในกรณีที่สองใช้"$@"เพื่อขยายตามปกติเป็น "พารามิเตอร์ตำแหน่งทั้งหมดยกเว้น $ 0" โปรดทราบว่าในกรณีนี้เราต้องส่งบางสิ่งบางอย่างเพื่อใช้เป็น$0เช่นกัน ฉันเลือก "ทุบตี" เพราะนั่นคือสิ่งที่$0ปกติจะได้ แต่สิ่งอื่นจะทำงาน

สำหรับเหตุผลที่ทำเช่นนี้แทนที่จะส่งผ่านอาร์กิวเมนต์ใด ๆ ที่คุณให้กับคำสั่งที่คุณระบุรายการโดยตรง: โปรดสังเกตว่าเอกสารอธิบายว่า "คำสั่งsอ่านจากสตริง" พหูพจน์ กล่าวอีกนัยหนึ่งโครงการนี้ให้คุณทำ:

/bin/bash -c 'mkdir "$1"; cd "$1"; touch "$2"' bash dir file

แต่โปรดทราบว่าวิธีที่ดีกว่าในการบรรลุเป้าหมายดั้งเดิมของคุณอาจใช้envแทนbash:

/usr/bin/env -- "ls" "-l"

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


3

ฉันไม่แน่ใจว่าเป้าหมายของคุณคืออะไร แต่ถ้าคุณแค่พยายามสร้างเครื่อง Rube Goldberg -“ การประดิษฐ์อุปกรณ์หรือเครื่องมือที่จงใจสร้างเกินหรือเกินจริงเพื่อทำงานง่ายๆในเวลาอันสั้น แฟชั่นที่ซับซ้อน” - จากนั้นลอง

sh -c 'ls $0' -l

หรือ

sh -c 'ls $1' supercalifragilisticexpialidocious -l

หรือแม้กระทั่ง

sh -c 'ls -$0' l

คุณควรเข้าใจวิธีการทำงานเหล่านี้จากคำตอบของ godlygeek

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