Сделайте bash функцию, которая принимает некоторые специальные символы в параметрах - PullRequest
0 голосов
/ 29 марта 2020

Начиная с этого ответа , я хочу заархивировать что-нибудь, используя "archive name_dest [folder+filter]"

Я пробовал:

archive() { tar cjf "`(date '+%Y.%m.%d-%Hh%Mm%Ss')`-$1.tar.bz2" "$2"; }

Когда я делаю это специальное предложение символы не обрабатываются:

> archive dev "dev/*"
tar: dev/*: Cannot stat: No such file or directory
tar: Exiting with failure status due to previous errors

(конечно, dev - это каталог в моем текущем пути) Каков правильный путь? Мне бы очень хотелось набрать only archive dev dev/*.

1 Ответ

3 голосов
/ 29 марта 2020

Символы подстановки (например, *) расширяются в список совпадающих имен файлов только тогда, когда они не в кавычках. Можно было бы оставить $2 без кавычек в функции:

archive() { tar cjf "`(date '+%Y.%m.%d-%Hh%Mm%Ss')`-$1.tar.bz2" $2; }

... но это может иметь некоторые неприятные последствия. Очевидно, что если вы пытаетесь заархивировать папку с пробелами или другими метасимволами в имени в имени, это может привести к путанице, потому что эти тоже не в кавычках.

A гораздо лучшее решение - передать шаблон папка + без кавычек, чтобы он расширялся до вызова функции. Вы запускаете

archive dev dev/*

... и оболочка расширяет его до чего-то вроде

archive dev dev/file1 dev/file2 dev/file3

Но тогда вам нужно написать функцию, чтобы она не просто архивировала $2, но все аргументы начинаются с $2. Это не так уж сложно; просто запишите $1, используйте shift, чтобы удалить его из списка аргументов, затем используйте "$@", чтобы получить все оставшиеся аргументы. И до тех пор, пока мы используем локальные переменные, я бы поставил целевое имя файла в одну (просто для общей аккуратности):

archive() {
    local name_dest="$1"
    local archive_name="$(date '+%Y.%m.%d-%Hh%Mm%Ss')-${name_dest}.tar.bz2"
    shift
    tar cjf "${archive_name}" "$@"
}
...