我在vec temp = w * A;
inplace_trans(A, "lowmem");
temp = temp * A;
w -= temp;
中有一些.txt
个文件:
dir1
以及file_name_FOO31101.txt
file_name_FOO31102.txt
file_name_FOO31103.txt
file_name_FOO31104.txt
中的一些相关foo.txt
文件:
dir2
我最终希望能够为一对文件调用一个程序,以便:
迭代1
file_name_FOO31101_foo.txt
file_name_FOO31102_foo.txt
file_name_FOO31103_foo.txt
file_name_FOO31104_foo.txt
迭代2
program_call \
--txt file_name_FOO31101.txt,file_name_FOO31102.txt \
--foo file_name_FOO31101_foo.txt,file_name_FOO31102_foo.txt \
--bar file_name_FOO31101_bar.txt,file_name_FOO31102_bar.txt
即。
program_call \
--txt file_name_FOO31103.txt,file_name_FOO31104.txt \
--foo file_name_FOO31103_foo.txt,file_name_FOO31104_foo.txt \
--bar file_name_FOO31103_bar.txt,file_name_FOO31104_bar.txt
file_name_FOO31101.txt,file_name_FOO31102.txt
但不
file_name_FOO31103.txt,file_name_FOO31104.txt
question I posted yesterday的回答让我开始:
file_name_FOO31102.txt,file_name_FOO31103.txt
然后(不知道更好的方法)我为#!/bin/bash
txt_files=/path/to/txt
foo_files=/path/to/foo/files
set -- "$txt_files"/*.txt
[[ -e $1 || -L $1 ]] || { echo "No .txt files found in $txt_files" >&2; exit 1; }
# $# = number of command line arguments passed to the script
while (( $# > 1 )); do
stem=$(basename "${1}" )
output_base=$(echo $stem | cut -d '_' -f 1,2,3) # split on '_' and save ID
echo "-> Processing pairs of txt files : $1,$2"
# Add files to array
txt1+=($1)
txt2+=($2)
shift; shift
done
(( $# )) && echo "Left over file $1 still exists"
中的foo
文件重复相同的循环:
dir2
然后迭代其中一个数组(所有数组必须长度相同)并调用程序:
set -- "$foo_files"/*_foo.txt
[[ -e $1 || -L $1 ]] || { echo "No foo.txt files found in $foo_files" >&2; exit 1; }
# $# = number of command line arguments passed to the script
while (( $# > 1 )); do
stem=$(basename "${1}" )
output_base=$(echo $stem | cut -d '_' -f 1,2,3) # split on '_' and save ID
# Add files to array
foo1+=($1)
foo2+=($2)
echo "-> Processing pairs of foo.txt files : $1,$2"
shift; shift
done
(( $# )) && echo "Left over file $1 still exists"
这似乎基本上有效,打印:
# Seeing as all arrays must be the same length, loop over one and print out corresponding values for others
for ((i=0;i<${#txt1[@]};++i)); do
printf "program_call --txt %s,%s --foo %s,%s\n" "${txt1[i]}" "${txt2[i]}" "${foo1[i]}" "${foo2[i]}"
done
但是,我怀疑对所有不同的dirs使用相同的while循环是实现此结果的一种不好的方法,特别是如果我想在我的程序调用中调用添加更多选项(例如program_call --txt /path/to/txt/file_name_FOO31101.txt,/path/to/txt/file_name_FOO31102.txt --foo /path/to/foo/files/file_name_FOO31101_foo.txt,/path/to/foo/files/file_name_FOO31102_foo.txt
program_call --txt /path/to/txt/file_name_FOO31103.txt,/path/to/txt/file_name_FOO31104.txt --foo /path/to/foo/files/file_name_FOO31103_foo.txt,/path/to/foo/files/file_name_FOO31104_foo.txt
...)
这是一种合理的解决方法吗?
答案 0 :(得分:0)
你的直觉是正确的:有比bash
循环和数组更快的方法。
这里是如何列出和排序两个目录中的文件:
find txt foo -type f -name "*.txt" | sort -t'/' -k2,2
输出:
txt/a_0001.txt
foo/a_0001_foo.txt
txt/a_0002.txt
foo/a_0002_foo.txt
txt/a_0003.txt
foo/a_0003_foo.txt
txt/a_0004.txt
foo/a_0004_foo.txt
...
接下来,假设任一目录中没有额外或丢失的文件,您可以使用awk
获得4 /行:
find txt foo -type f -name "*.txt" | sort -t'/' -k2,2 |
awk '{printf $1" "; if(NR%4==0)printf "\n"}'
输出:
txt/a_0001.txt foo/a_0001_foo.txt txt/a_0002.txt foo/a_0002_foo.txt
txt/a_0003.txt foo/a_0003_foo.txt txt/a_0004.txt foo/a_0004_foo.txt
txt/a_0005.txt foo/a_0005_foo.txt txt/a_0006.txt foo/a_0006_foo.txt
...
接下来,您可以使用另一个awk
重新排序它们并创建命令字符串:
find txt foo -type f -name "*.txt" | sort -t'/' -k2,2 |
awk '{printf $1" "; if(NR%4==0)printf "\n"}' |
awk '{print "program_call --txt "$1","$3" --foo "$2","$4}'
输出:
program_call --txt txt/a_0001.txt,txt/a_0002.txt --foo foo/a_0001_foo.txt,foo/a_0002_foo.txt
program_call --txt txt/a_0003.txt,txt/a_0004.txt --foo foo/a_0003_foo.txt,foo/a_0004_foo.txt
...
基准测试,使用fugu的代码与find|sort|awk|awk
从2000个文件制作500个命令字符串:
bash loops & arrays 10.070s
find|sort|awk|awk 0.019s
超过500倍的速度:)
您还可以通过使用管道而不是循环来运行命令字符串来节省时间:
find txt foo -type f -name "*.txt" | ... | sh
通过管道命令而不是GNU parallel
通常更多的时间:
find txt foo -type f -name "*.txt" | ... | parallel
(如果您的系统上尚未安装parallel
,则可能需要安装。)