将 glob 表达式传递给函数/脚本

将 glob 表达式传递给函数/脚本

以下脚本应该将csv第一个参数中指定的路径中的多个文件连接到第二个参数中指定的单个 csv 文件中

#!/bin/zsh
set -x
set -v
args=("$@");
globbing_pattern=${args[1]}
output_file=${args[2]}

# First the headers:
head -n1 ${globbing_pattern}([1,1]) > $output_file

# Now concatenate everything:
find ${globbing_pattern} -print0 | xargs -0 cat >> $output_file

我想用以下方式调用这个脚本:

my_script '/some/path/*.csv' output.csv

但它不起作用。我得到:

find: /some/path/*.csv: No such file or directory

为什么?

答案1

查找:/some/path/*.csv:

发现sytanx是错误的。

要查找给定文件夹树中以 .csv 结尾的所有文件:

find /some/path -name "*.csv"

因此,您需要将文件的位置和名称分开。

答案2

zsh除非用语法告知,否则不会扩展变量中的通配符$~PATTERN

我会这样写:

#! /bin/sh -
head -n -- "$1"
cat -- "$@"

并将其用作:

my-script /some/path/*.csv > output.csv

这样,您仍然可以对脚本的输出进行后处理,并且通配符是在用户的 shell 中完成的。现在,如果您确实希望由脚本完成通配符,例如为了克服“参数过多”限制,或者因为您确实想要 zsh 通配符而不管用户的 shell,并且您确实希望脚本编写输出文件(例如,为了防止它作为输入文件出现,或者如果没有输入文件则不创建它),您需要编写它:

#! /bin/zsh -
files=(${~1?}) output=${2?}
head -n 1 -- $files[1]
printf '%s\0' $files | xargs -r0 cat -- > $output

或者与zsh's zargs

#! /bin/zsh -
files=(${~1?}) output=${2?}
head -n 1 -- $files[1]
autoload zargs
zargs --eof= -- $files '' cat -- > $output

现在,我不确定这确实是您想要的,因为这意味着“标题”将显示两次。另请注意,调用的文件-可能会出现问题。

也许你真的想要(用 GNU 尾巴):

#! /bin/zsh -
setopt extendedglob
files=(${~1?}) output=${2?}
cat < $files[1]
autoload zargs
zargs --eof= -- $files[2,-1] '' tail -qn +2 -- > $output

(这里使用 Extendedglob,这样您就可以从完整的 zsh globbing 中受益)。

相关内容