我有一个程序可以按特定顺序读取文件。对于此示例,它们都具有相同的扩展名 txt
{program_name} {input 1...} {output}
我碰巧将输出文件名命名为“a.txt”,因此它是我调用时的第一个结果ls
,它显示了输入到此命令的文件的顺序:
{program_name} *.txt
我希望第一个结果显示为最后一个结果。如何颠倒星星匹配的顺序?如果我需要使用管道,正确输入参数以便正确引用任何特殊字符或空格的语法是什么?
答案1
利用zsh
:
zsh -c 'program *.txt(.^on)'
是模式的修饰符(.^on)
,使其仅匹配常规文件 (the ),并且将以相反 ( ) 字典顺序( ) 对结果列表进行排序 ( )。zsh
*.txt
.
o
^
n
这将启动一个非交互式zsh
shell,该 shell 将以program
生成的文件名列表作为命令行参数运行。该命令将正确处理反转参数列表,即使它们在文件名中包含空格或换行符等。
例子:
$ touch {a..d}.txt
$ echo *.txt
a.txt b.txt c.txt d.txt
$ zsh -c 'echo *.txt(.^on)'
d.txt c.txt b.txt a.txt
非zsh
解:
set --
for fname in *.txt; do
set -- "$fname" "$@"
done
program "$@"
或者,在例如中使用命名数组bash
,
args=()
for fname in *.txt; do
args=( "$fname" "${args[@]}" )
done
program "${args[@]}"
在这两个代码片段中,数组都是根据与*.txt
模式匹配的名称构建的。每个名字都被推到数组的前面,所以效果是数组最终以姓氏在前。
在第一个实例中,我们使用位置参数列表作为数组。该代码应该可以在任何sh
类似的 shell 中工作。
如果您只需要程序参数列表中的名字位于最后,并且可以让其他名称按照它们扩展的顺序排列,那么下面的代码就可以做到这一点(在任何sh
类似的 shell 中):
set -- *.txt
fname=$1
shift
program "$@" "$fname"
或者,使用bash
特定语法和命名数组,
args=( *.txt )
program "${args[@]:1}" "${args[0]}"
"${args[@]:1}"
将从 element 开始扩展到args
数组的所有元素(单独引用)1
。
再次测试echo
:
$ args=( *.txt )
$ echo "${args[@]:1}" "${args[0]}"
b.txt c.txt d.txt a.txt