Xây dựng một lệnh động


9

Tôi đang làm việc trên một kịch bản và tôi cần xây dựng tarlệnh một cách linh hoạt.

Đây là hai ví dụ để minh họa những gì tôi đang cố gắng làm:

#!/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"

Tôi muốn có thể sử dụng _tarnhư một lệnh, tôi đã có thể làm cho nó hoạt động với đường dẫn cổ điển, nhưng tôi cần nó để làm việc với các khoảng trắng trong tên thư mục. Và mỗi lần tôi gặp lỗi giống như:

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

Chỉ cần một điều bạn cần biết, tôi cần kịch bản của mình để hoạt động trên các máy rất cũ, nghĩa là tôi không thể sử dụng các tính năng bash cuối cùng.


Tôi tin rằng tùy chọn --exclude chỉ có thể chấp nhận một chuỗi sau nó. Bạn có thể có nhiều câu lệnh --exclude mặc dù. Có thể thử "--exclude = / tmp / hello --exclude = hello" Rất tiếc. Đừng bận tâm. Tôi đã hiểu nhầm.
Lewis M

@LewisM Tôi nghĩ OP muốn loại trừ thư mục "/ tmp / xin chào xin chào" (vâng, với một khoảng
trắng

@ShellCode những gì về trích dẫn tất cả loại trừ, ví dụ: "--exclude = / tmp / xin chào xin chào"
Archemar

Vâng. Đó là lý do tại sao tôi đặt câu lệnh Oops sau. :)
Lewis M

Làm thế nào về việc đặt evaltrước khi thực hiện?
jimmij

Câu trả lời:


11

Đừng cố tạo một chuỗi thực thi. Thay vào đó, hãy xây dựng các đối số trong một mảng và sử dụng điều đó khi gọi tar(bạn đã sử dụng đúng một mảng cho 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"

Với /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"

Lưu ý trích dẫn $@trong shmã và của cả hai ${exclude[@]}${exclude_opts[@]}trong bashmã. Điều này đảm bảo rằng các danh sách được mở rộng thành các yếu tố được trích dẫn riêng lẻ.

Liên quan:


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[@]}"

Mở rộng câu trả lời ở đây . Điều này không phụ thuộc vào bất kỳ bashism nào, nó cũng sẽ hoạt động tốt với debian /bin/shvà với busybox.


Cảm ơn bạn rất nhiều vì sự giúp đỡ của bạn, nhưng tôi không thực sự thích eval, nó khá nguy hiểm ... Hơn nữa, mã này khá khó hiểu, bạn có điều gì dễ dàng hơn không? : / Kịch bản sẽ được phân phối vì vậy tôi phải giữ nó đơn giản nhất có thể ...
ShellCode

Nó không nguy hiểm. Chạy nó với set -x. Chính xác thì bạn không hiểu gì?
mosvy

Ngoài ra, đọc câu trả lời ban đầu trên stackoverflow. Nó bao gồm một bản demo.
mosvy

Nó hoạt động khá tốt mặc dù ... Chờ xem có ai có câu trả lời rõ ràng hơn không, nếu không tôi sẽ chấp nhận của bạn. Có thể không có gì sai với mã đó, nhưng mỗi khi tôi thấy một eval, tôi sợ mã đó có thể dẫn đến lệnh tiêm, đó là lý do tại sao tôi cố gắng tránh nó
ShellCode

Tôi đã cập nhật câu trả lời với bản sửa lỗi cho các chỉ mục> 9. Bạn có thể thay thế eval bằng tiếng vang để xem những gì thực sự nhận được (eval không thấy tên tệp)
mosvy
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.