2011-11-23 79 views
2

我有,以这种方式处理参数的操作f如何使用文件列表一次调用两个可执行文件?

f(f(f(a,b),c),d)... 

f是一个程序,参数是文件名。它通常被称为是这样的:

f a b | f - c | f - d > result 

是否有一个简短的bash方式使此调用更容易?我有 文件的列表,说*.txt,我想打电话f这些文件,东西 像

callpairs(f, *.txt) > result 

回答

0

在此期间,我写了这个小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 
2

我给你纯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版本将会失败这些测试。)

相关问题