我有,以这种方式处理参数的操作f
:如何使用文件列表一次调用两个可执行文件?
f(f(f(a,b),c),d)...
f
是一个程序,参数是文件名。它通常被称为是这样的:
f a b | f - c | f - d > result
是否有一个简短的bash方式使此调用更容易?我有 文件的列表,说*.txt
,我想打电话f
这些文件,东西 像
callpairs(f, *.txt) > result
我有,以这种方式处理参数的操作f
:如何使用文件列表一次调用两个可执行文件?
f(f(f(a,b),c),d)...
f
是一个程序,参数是文件名。它通常被称为是这样的:
f a b | f - c | f - d > result
是否有一个简短的bash方式使此调用更容易?我有 文件的列表,说*.txt
,我想打电话f
这些文件,东西 像
callpairs(f, *.txt) > result
在此期间,我写了这个小perl脚本callpairs
,做它:
my ($exe, @args) = @ARGV;
if (!defined $exe || !defined $ARGV[0] || !defined $ARGV[1]) {
die;
}
my $f1 = shift @args;
my $f2 = shift @args;
my $cmd = "$exe $f1 $f2";
while (scalar @args) {
my $f = shift @args;
$cmd .= " | $exe - $f";
}
print "$cmd\n";
可以这样调用:
callpairs f *.txt | bash
我给你纯BAS两个版本H。两者都使用数组分片来获取参数组(例如"${@:1:3}"
给出前三个参数)。两者还保持对文件参数的引用(以便您可以在名称中包含空格的文件上使用它们),但不保留在命令本身上(因此,您可以使用例如callpairs "sort -f" file1 file2 file3
,它将-f
作为sort命令的选项,而不是命令名的一部分)。
首先,这里有一个递归版本:
#!/bin/bash
args=$#
if [ $args -lt 3 ]; then
echo "Usage: $0 command file1 file2 [file3 ...]" >&2
exit 1
elif [ $args -eq 3 ]; then
$1 "$2" "$3"
else
"$0" "${@:1:$args-1}" | $1 - "${!args}"
fi
及这里的构建整个命令管道作为字符串版本,然后eval
的IT:
#!/bin/bash
if [ $# -lt 3 ]; then
echo "Usage: $0 command file1 file2 [file3 ...]" >&2
exit 1
fi
cmd="$(printf "%s %q %q" "${@:1:3}")"
for file in "${@:4}"; do
cmd+="$(printf " | %s - %q" "$1" "$file")"
done
eval "$cmd"
这里警告一下: eval
如果你没有得到你的报价和逃避恰到好处,就会有引起错误的良好声誉。我认为我在这里得到了它(我用名称中的空格测试了一个文件,另一个文件名为a$(halt).txt
- 只是触发评估错误的东西),但没有绝对的保证。 (顺便说一句,perl版本将会失败这些测试。)