Предварительный текст к каждому аргументу подстановочного знака в bash
Простой пример: mybin *.txt
будет расширяться до mybin a.txt b.txt c.txt
Но я ищу простое решение для расширения что-то вроде: mybin --conf a.txt --conf b.txt --conf c.txt
,
Есть ли встроенный в это? Какой самый простой способ для этого?
5 ответов
find
мой друг:
mybin $(find /wherever/ -name '*.txt' -printf '--conf %p ')
Немного хитрое решение:
eval mybin "--conf\ {`echo *.txt|tr -s " " ,`}"
Для всех текстовых файлов
eval mybin "$(printf -- '--conf %q ' *.txt)"
Если только для определенных текстовых файлов
eval mybin '--conf "'{a,b,c}.txt'"'
Может быть, мы должны использовать функцию-оболочку. Это не встроенное решение, но оно работает лучше, чем две предыдущие команды, если имена файлов содержат пробелы или специальные символы.
функция mybinw
:
function mybinw() {
declare -a mybin_opts
for file in "$@"; do
mybin_opts+=(--conf "$file")
done
mybin "${mybin_opts[@]}"
}
Тестовое задание:
mybin
:
#!/bin/bash
for q in "$@"; do
echo "=> $q"
done
Создайте несколько текстовых файлов, некоторые имена файлов содержат пробелы или специальные символы
touch {a,b,c,d,efg,"h h"}.txt 'a(1).txt' 'b;b.txt'
Для всех текстовых файлов:
eval mybin "$(printf -- '--conf %q ' *.txt)"
=> --conf => a(1).txt => --conf => a.txt => --conf => b;b.txt => --conf => b.txt => --conf => c.txt => --conf => d.txt => --conf => efg.txt => --conf => h h.txt
для определенных текстовых файлов:
eval mybin '--conf "'{a,b,c,"h h"}.txt'"'
=> --conf => a.txt => --conf => b.txt => --conf => c.txt => --conf => h h.txt
Использование функции-обертки
touch 'c"c.txt'
mybinw *.txt
=> --conf => a(1).txt => --conf => a"b.txt => --conf => a.txt => --conf => b;b.txt => --conf => b.txt => --conf => c"c.txt => --conf => c.txt => --conf => d.txt => --conf => efg.txt => --conf => h h.txt
# usage mix command switch args ...
mix(){
p=$1; shift; q=$1; shift; c=
i=1; for a; do c="$c $q \"\${$i}\""; i=$((i+1)); done
eval "$p $c"
}
mix mybin --conf *.txt
Это переносимо для любой оболочки POSIX, а не только bash
и может обрабатывать имена файлов с пробелами, специальными символами и т.д.:
$ qecho(){ for a; do echo "{$a}"; done; }
$ touch 'a;b' "a'b" "a\\'b" 'a"b' 'a\"b' '(a b)' '(a b)' 'a
b'
$ mix qecho --conf *
{--conf}
{(a b)}
{--conf}
{(a b)}
{--conf}
{a
b}
{--conf}
{a"b}
{--conf}
{a'b}
{--conf}
{a;b}
{--conf}
{a\"b}
{--conf}
{a\'b}
set -- *.txt
for thing do
shift
set -- "$@" --conf "$thing"
done
mybin "$@"
Это будет использовать список позиционных параметров ($@
), чтобы держать расширенный шаблон шара. Затем мы перебираем эти элементы и модифицируем $@
вставив --conf
перед каждым. mybin
утилита может быть вызвана с этим списком.
Цитирование в коде является намеренным, чтобы не дать оболочке разбить любые строки на пробелах и развернуть любые глобусы имен файлов, если они встречаются как надлежащие части имен файлов, которые *.txt
Матчи.
bash
-специфическое отклонение:
files=( *.txt )
for thing in "${files[@]}"; do
args+=( --conf "$thing" )
done
mybin "${args[@]}"
Короче вариации обоих вышеперечисленных. Сначала для /bin/sh
:
set --
for thing in *.txt; do
set -- "$@" --conf "$thing"
done
mybin "$@"
Тогда для bash
:
for thing in *.txt; do
args+=( --conf "$thing" )
done
mybin "${args[@]}"
В качестве функции оболочки:
delim_run () {
cmd=$1
delim=$2
shift 2
for thing do
shift
set -- "$@" "$delim" "$thing"
done
"$cmd" "$@"
}
Тогда вы сможете сделать
delim_run mybin --conf *.txt