Существуют инструменты Python
$pip install humanfriendly # Also available as a --user install in ~/.local/bin
$humanfriendly --format-size=2048
2.05 KB
$humanfriendly --format-number=2048
2,048
Я не вижу --двоичного флага :(, поэтому вам придется использовать Python напрямую для двоичного представления:
$python -c 'import sys, humanfriendly; print(humanfriendly.format_size(int(sys.argv[1]), binary=True))' 2048
2 KiB
$python -c 'import sys, humanfriendly; print(humanfriendly.format_size(int(sys.argv[1]), binary=True))' 2000
1.95 KiB
Попробуйте добавить экранированные кавычки вокруг массива следующим образом
backupcommand="rsync -ar \"${a[@]}\" dest/"
Сначала нам нужен способ показать, что у нас есть в нашем массиве bash, sources
. Кажется, хорошим способом является использование printf '%s\n' <args>
, который будет выводить по одной строке для каждого аргумента в <args>
.
Например:
$ sources=( file1 file2 "other stuff" )
$ printf '%s' "${sources[@]}"
file1
file2
other stuff
Если мы используем эту команду в качестве backupcommand
, мы можем увидеть, что программа резервного копирования (, например.rsync
)фактически получит в качестве своих аргументов. Предположим, что команда, которую мы хотим запустить черезbash -c...
(или ssh...
), это printf '%s\n' <args>
и что у нас есть два аргумента, file1
и other stuff
.
Мы хотим запустить эту команду в целевой оболочке:
$ printf '%s\n' file1 other\ stuff
file1
other stuff
Итак, чтобы получить это как один аргумент, нам нужно процитировать его. Мы можем использовать ""
, ''
или \
для цитирования. Мы можем снова использовать printf '%s\n'
, чтобы убедиться, что мы сделали это успешно...
$ # With backslashes:
$ printf '%s\n' printf\ \'%s\\n\'\ file1\ other\\\ stuff
printf '%s\n' file1 other\ stuff
$ # With single quotes
$ printf '%s\n' 'printf '\''%s\n'\'' file1 other\ stuff'
printf '%s\n' file1 other\ stuff
$ # Using a variable to store the command...
$ the_command='printf '\''%s\n'\'' file1 other\ stuff'
$ #..then using that variable as a single argument...
$ printf '%s\n' "$the_command"
printf '%s\n' file1 other\ stuff
Пока все хорошо. В последней версии мы указали переменную, содержащую команду.
Теперь мы можем использовать массив для аргументов? Что нам нужно сделать, так это заключить в кавычки/экранировать каждый элемент массива и добавить его к одной строке the_command
.
${var[@]}
указывает bash создавать один токен для каждого элемента массива. Но они не экранированы, потому что они уже были интерпретированы. Поэтому мы не можем просто добавить это в командную строку оболочки. Итак, нам нужен способ применения цитирования.
Баш имеет printf '%q' arg
, чтобы процитировать arg
. Мы можем использовать подстановку команд$(...)
$ sources=( file1 other\ stuff )
$ the_command=printf\ \'%s\\n\'
$ for item in "${sources[@]}"
do the_command="$the_command "$(printf '%q' "$item")
done
$ printf '%s\n' "$the_command"
printf '%s\n' file1 other\ stuff
Ура! Однако,мы можем почистить это примерно так:
$ sources=( file1 other\ stuff )
$ the_command="printf '%s\\n'"$(printf ' %q' "${sources[@]}")
$ printf '%s\n' "$the_command"
printf '%s\n' file1 other\ stuff
$ # And as final proof...
$ bash -c "$the_command"
file1
other stuff
sources=( file1 file2 "other stuff" )
backupcommand="rsync -ar "$(printf ' %q' "${sources[@]}")" dest/"
su backupuser -c "$backupcommand"
printf '%q' arg
цитатыarg
$(...)
создает один маркер из вывода команды.