在 bash 中的每个"wildcard"参数前面加上一些文本



一个简单的例子:mybin *.txt将扩展到mybin a.txt b.txt c.txt

但是我正在寻找一个简单的解决方案来扩展到以下内容:mybin --conf a.txt --conf b.txt --conf c.txt.

是否有内置功能可以执行此操作?最简单的方法是什么?

find是我的朋友:

mybin $(find /wherever/ -name '*.txt' -printf '--conf %p ')

有点棘手的解决方案:

eval mybin "--conf {`echo *.txt|tr -s " " ,`}"

适用于所有 txt 文件

eval mybin "$(printf -- '--conf %q ' *.txt)"

如果仅适用于某些 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

创建一些txt文件,一些文件名包含空格或特殊字符

touch {a,b,c,d,efg,"h h"}.txt 'a(1).txt' 'b;b.txt'

对于所有 txt 文件:

eval mybin "$(printf -- '--conf %q ' *.txt)"

某些 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 shell,而不仅仅是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实用程序。

代码中的引号是故意阻止 shell 拆分空格上的任何字符串,并扩展任何文件名 glob(如果它们作为*.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

相关内容

  • 没有找到相关文章

最新更新