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