根据整数数组过滤文件列表?

根据整数数组过滤文件列表?

我有一个包含很多图像的文件夹,名为“剪辑01234-randomlongstring.png“, 在哪里01234是一个随机的五位数字。我也有一个数组“剪辑编号" 带有整数列表。

现在我想创建一个列表“文件”,其中包含与“中的数字匹配的所有文件名”剪辑编号“数组。我该怎么做呢?

结果输出应该是我可以用与我创建的当前列表(所有文件)相同的方式处理的内容: files=($(printf "%s\n" *.* | sort -V | tr '\n' ' '))

答案1

在循环中:

shopt -s nullglob

files=()
for number in "${clipnumbers[@]}"; do
    printf -v pattern 'clip%s-*.png' "$number"
    files+=( $pattern )
done

这会循环遍历数字并为每个数字创建一个文件名通配模式。该模式被扩展以将与其匹配的文件名添加到数组中files。 shellnullglob选项使不匹配的模式展开为空(而不是保持未展开)。


使用find(用于递归到当前目录下的所有目录,并对每个找到的文件执行某些操作):

patterns=()
for number in "${clipnumbers[@]}"; do
    printf -v pattern 'clip%s-*.png' "$number"
    patterns+=( -o -name "$pattern" )
done

find . -type f \( "${patterns[@]:1}" \) -exec action-to-perform-on-files {} \;

从扩展中的列表中删除:1首字母。-opatterns

这将搜索文件与对文件执行某些操作结合起来。它会失败如果您的clipnumbers数组包含数千个数字(参数列表会变得太长)。

答案2

选项1

如同拘萨罗南达的回答但使用数组扩展而不是循环:

设置

$ touch clip12710-x.png  clip30443-x.png  clip57592-x.png  clip76672-x.png  clip93493-x.png
$ declare -a array=([0]="30443" [1]="76672" [2]="42424")

请注意,该数组仅包含两个预期匹配的项目;有些文件名的剪辑是不是存在并且有剪辑编号array存在并且其中不是作为文件名存在。

执行

$ shopt -s nullglob
$ pfiles=( "${array[@]/#/clip}" )
$ oIFS="$IFS"
$ IFS=
$ pfiles=( ${pfiles[@]/%/-*.png} )
$ IFS="$oIFS"
$ declare -p pfiles
declare -a pfiles=([0]="clip30443-x.png" [1]="clip76672-x.png")

请注意,第一个赋值中小心地包含了双引号,而第二个赋值中则没有双引号。初始分配将数字的“array”数组转换为部分文件名的“pfiles”数组:前置字符串clip每个元素的。第二次作业追加-*.png数组中每个元素的通配符;此赋值中缺少引号允许 shell 拆分每个元素$IFS(通常是空格、制表符和换行符),但我们暂时将 IFS 覆盖为空。然后 shell 还会“globs”结果,这就是我们在这里想要的——它将“clip...*-png”名称扩展为任何匹配的文件名。设置 shell 选项后nullglob,任何不匹配的通配符都会被删除。最终结果是 pfiles 中与原始数组中的剪辑编号相匹配的文件数组。


选项#2

(虐待扩展的通配符:

shopt -s extglob nullglob
declare -a array=([0]="30443" [1]="76672" [2]="42424")
oIFS="$IFS"
IFS='|'
p="${array[*]}"
IFS="$oIFS"
pfiles=( clip@($p)-*.png )

这是通过将 IFS 设置为管道符号来实现的|,以便后续对pof 的赋值array[*]连接 by 管道的元素array(此时 $IFS 的第一个字符)。管道是 bash 的扩展通配语法在扩展通配模式中的选项之间所需的分隔符。最后一行扩展为与我们构建的扩展 glob 模式匹配的文件数组:

  • 从...开始clip
  • 包含给定模式之一(剪辑编号),现在包含在变量中p
  • 然后是-任何东西
  • 并结束于.png

nullglob如果您的剪辑数组不与任何现有文件名重叠,则需要 shell 选项。

答案3

zsh

clipnumbers=(01234 33333)
files=(clip$^clipnumbers-*.png(N.))

这会为每个剪辑编号扩展一个 glob。或者,您可以将数组转换为全局交替运算符:

files=(clip(${(j:|:)~clipnumbers})-*.png(N.))

答案4

mapfile -t files <  <( shopt -s nullglob ; printf "%s\n" $(printf "clip%s-*.png " "${clipnumbers[@]}" ) )
  • mapfile -t files将行作为数组读入文件,去掉尾随换行符。
  • shopt -s nullglob将不存在的模式扩展为空字符串
  • printf "%s\n" ...展开模式,每行一个。
  • $(printf "clip%s-*.png " "${arr[@]}") )构建模式。

相关内容