反转文件匹配的顺序作为参数

For*_*ker 2 ls bash pipe shell-script

我有一个按特定顺序读取文件的程序。对于这个例子,它们都有相同的扩展名,txt

{program_name} {input 1...} {output}
Run Code Online (Sandbox Code Playgroud)

我碰巧将输出文件名命名为“a.txt”,因此它是我调用时的第一个结果ls,它显示了提供给此命令的文件的顺序:

{program_name} *.txt
Run Code Online (Sandbox Code Playgroud)

我希望第一个结果显示为最后一个。如何颠倒星号匹配的顺序?如果我需要使用管道,正确输入参数以便正确引用任何特殊字符或空格的语法是什么?

Kus*_*nda 5

利用zsh:

zsh -c 'program *.txt(.^on)'
Run Code Online (Sandbox Code Playgroud)

The(.^on)是模式的zsh修饰符*.txt,使其仅匹配常规文件 (the .) 并且将按o相反 ( ^) 字典顺序 ( n)对结果列表进行排序 ( )。

这将启动一个非交互式zshshell,它将program使用生成的文件名列表作为命令行参数运行。该命令将正确处理反转参数列表,即使它们在文件名中包含空格或换行符等。

例子:

$ touch {a..d}.txt
$ echo *.txt
a.txt b.txt c.txt d.txt
Run Code Online (Sandbox Code Playgroud)
$ zsh -c 'echo *.txt(.^on)'
d.txt c.txt b.txt a.txt
Run Code Online (Sandbox Code Playgroud)

一个非zsh解决方案:

set --
for fname in *.txt; do
    set -- "$fname" "$@"
done

program "$@"
Run Code Online (Sandbox Code Playgroud)

或者,在 eg 中使用命名数组bash,

args=()
for fname in *.txt; do
    args=( "$fname" "${args[@]}" )
done

program "${args[@]}"
Run Code Online (Sandbox Code Playgroud)

在这两个代码片段中,一个数组是根据与*.txt模式匹配的名称构建的。每个名字都被推到前面的数组上,所以结果是数组最后有姓氏。

在第一个实例中,我们使用位置参数列表作为数组。该代码应该在任何sh类似 shell 中工作。


如果您只需要程序参数列表中最后的名字,并且可以让其他名称按照它们展开的顺序排列,那么以下将执行此操作(在任何sh类似 shell 中):

set -- *.txt
fname=$1
shift
program "$@" "$fname"
Run Code Online (Sandbox Code Playgroud)

或者,使用bash-specific 语法和命名数组,

args=( *.txt )
program "${args[@]:1}" "${args[0]}"
Run Code Online (Sandbox Code Playgroud)

"${args[@]:1}"args将从元素1开始扩展到数组的所有元素(单独引用)。

再次测试echo:

$ args=( *.txt )
$ echo "${args[@]:1}" "${args[0]}"
b.txt c.txt d.txt a.txt
Run Code Online (Sandbox Code Playgroud)