我有一个包含文件的文件夹。每个文件的名称可以分为三个部分:名称 - 所有文件都相同; key - 一些关键字,根据这些关键字,文件可以分为3组;结束号码(1..10) - 组内的位置。例如:
第一组文件,由“key 1”
定义name_key1_1
name_key1_2
name_key1_3
..
name_key1_10
第二组文件,由“key 2”
定义name_key2_1
name_key2_2
name_key2_3
..
name_key2_10
第三组文件,由“key 3”
定义name_key3_1
name_key3_2
name_key3_3
..
name_key3_10
现在我需要循环所有文件,目的是将它们传递给某个程序,该程序组合了来自同一组(密钥)的文件。每次我只需要使用相同的密钥传递文件,以便将它们组合在一起(避免在每次处理期间将文件与其他密钥混合)。因此,有3组文件,应使用以下方法创建三个组合文件:
for file in ${input}/*.xtc; do
file_name=$(basename "$file")
prog -f ${input}/${name}_${key}_* -o ${output}/${name}_${key}_combined.xtc -cat
done
在这个例子中,通过执行prog,我需要组合来自每个组的10个文件(使用相同的密钥),避免与来自另一个组的文件混合。
我将非常感谢这个工作流程的实现及其过滤器的应用,例如基于从文件名中获取的自动检测到的组的数量。
答案 0 :(得分:0)
我建议使用以下代码,假设循环时$ {name}没有改变。
/编辑: 由于@tripleee是对的,我们应该使用find而不是ls
#!/bin/bash
input="/tmp/test/"
output="/tmp/"
name="foo"
for key in $(find ${input} -maxdepth 1 -mindepth 1 -type f -printf "%f\n" | rev| cut -d"_" -f2 | rev | sort | uniq ); do
for file in $(find ${input} -maxdepth 1 -mindepth 1 -type f -name \*_${key}_\* -print | sort ); do
prog -f ${file} -o ${output}/${name}_${key}_combined.xtc -cat
done
done
答案 1 :(得分:0)
如果字段由下划线分隔,并且值中没有其他下划线(即所有文件名只包含两个下划线),则只需在下划线上拆分。
for file in ${input}/*.xtc; do
oldIFS=$IFS
IFS=_
set -- ${file#"$input"/}
IFS=$oldIFS
dest="${output}/${1}_${2}_combined.xtc"
test -e "$dest" && continue
prog -f "${input}/${1}_${2}_"{1..10} -o "$dest" -cat
done
命令set -- string
将string
的值$IFS
拆分为$1
,并填充位置参数$2
,$3
,${variable#prefix}
等结果。参数展开$variable
会返回prefix
的值,并删除prog
(如果找到)。
我们粗暴地遍历所有文件,但如果输出文件已经存在,请跳过 base=${file%_*}
tail=${file#"$base"}
head=${base%_"$tail"}
dest="$outputdir/${head#$input/}_combined.txt"
test -e "$dest" && continue
:
。
如果您需要从末端剥离下划线,可能会在循环内部出现这样的情况:
${variable#suffix}
其中@user
删除后缀。
如果您可以重新设计输入的结构,那么组 - 以及它们之前的名称 - 也是子目录,这将使得处理集合时没有任何其他逻辑非常自然和直接。