สร้างคำสั่งแบบไดนามิก


9

ฉันกำลังทำงานกับสคริปต์และฉันต้องสร้างtarคำสั่งแบบไดนามิก

ต่อไปนี้เป็นสองตัวอย่างเพื่ออธิบายสิ่งที่ฉันพยายามทำ:

#!/bin/bash

TAR_ME="/tmp"

EXCLUDE=("/tmp/hello hello" "/tmp/systemd*" "/tmp/Temp*")
_tar="tar "`printf -- '--exclude="%s" ' "${EXCLUDE[@]}"`" -zcf tmp.tar.gz"
echo COMMAND: "${_tar}"
${_tar} "$TAR_ME"

echo -e "\n\nNEXT:\n\n"

EXCLUDE=("--exclude=/tmp/hello\ hello" "--exclude=/tmp/systemd*" "--exclude=/tmp/Temp*")
_tar="tar "`printf -- '%s ' "${EXCLUDE[@]}"`" -zcf test.tar.gz"
echo COMMAND: "${_tar}"
${_tar} "$TAR_ME"

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

COMMAND: tar --exclude="/tmp/hello hello" --exclude="/tmp/systemd*" --exclude="/tmp/Temp*"  -zcf tmp.tar.gz /tmp
tar: hello": Cannot stat: No such file or directory

COMMAND: tar --exclude=/tmp/hello\ hello --exclude=/tmp/systemd* --exclude=/tmp/Temp*  -zcf test.tar.gz 
tar: hello: Cannot stat: No such file or directory

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


ฉันเชื่อว่าตัวเลือก - ยกเว้นสามารถยอมรับได้เพียงสายเดียวหลังจากนั้น คุณสามารถมีคำสั่ง - ยกเว้นหลายรายการได้ อาจลอง "--exclude = / tmp / hello --exclude = hello" โอ๊ะโอ ไม่เป็นไร. ฉันเข้าใจผิด.
Lewis M

@LewisM ฉันคิดว่า OP ต้องการยกเว้นไดเรกทอรี "/ tmp / hello hello" (ใช่มีช่องว่าง
Archemar

@ShellCode สิ่งที่เกี่ยวกับการอ้างอิงทั้งหมดยกเว้นเช่น "--exclude = / tmp / hello hello"
Archemar

ใช่. นั่นเป็นเหตุผลที่ฉันใส่คำสั่งโอ๊ะโอในภายหลัง :)
Lewis M

วิธีการวางevalด้านหน้าของการประหารชีวิต?
jimmij

คำตอบ:


11

อย่าพยายามสร้างสตริงที่เรียกใช้งานได้ สร้างอาร์กิวเมนต์ในอาร์เรย์แทนและใช้สิ่งนั้นเมื่อโทรtar(คุณใช้อาร์เรย์อย่างถูกต้องแล้วEXCLUDE):

#!/bin/bash

directory=/tmp

exclude=( "hello hello" "systemd*" "Temp*" )

# Now build the list of "--exclude" options from the exclude array:
for elem in "${exclude[@]}"; do
    exclude_opts+=( --exclude="$directory/$elem" )
done

# Run tar
tar -cz -f tmp.tar.gz "${exclude_opts[@]}" "$directory"

ด้วย/bin/sh:

#!/bin/sh

directory=/tmp

set -- "hello hello" "systemd*" "Temp*"

# Now build the list of "--exclude" options from the $@ array
# (overwriting the values in $@ while doing so)
for elem do
    set -- "$@" --exclude="$directory/$elem"
    shift
done

# Run tar
tar -cz -f tmp.tar.gz "$@" "$directory"

จดบันทึกการอ้างถึง$@ในshรหัสและของทั้ง${exclude[@]}และ${exclude_opts[@]}ในbashรหัส สิ่งนี้ทำให้มั่นใจได้ว่ารายการจะถูกขยายไปยังองค์ประกอบที่ยกมาเป็นรายบุคคล

ที่เกี่ยวข้อง:


2
mix(){
        p=$1; shift; q=$1; shift; c=
        i=1; for a; do c="$c $q \"\${$i}\""; i=$((i+1)); done
        eval "${p%\%*}$c${p#*\%}"
}
mix 'tar % -zcf tmp.tar.gz' --exclude "/tmp/hello hello" "/tmp/systemd*" "/tmp/Temp*"

EXCLUDE=("/tmp/hello hello" "/tmp/systemd*" "/tmp/Temp*")
mix 'tar % -zcf tmp.tar.gz' --exclude "${EXCLUDE[@]}"

ขยายคำตอบที่นี่ นี้ไม่ได้พึ่งพา bashisms ใด ๆ ก็จะยังทำงานได้ดีกับเดเบียนของและมี/bin/shbusybox


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

มันไม่อันตราย set -xเรียกมันด้วย อะไรที่คุณไม่เข้าใจ
mosvy

และอ่านคำตอบดั้งเดิมของ stackoverflow ด้วย มันรวมถึงการสาธิต
mosvy

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

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