8个文件作为Linux shell脚本中的输入组合

bkhjykvo  于 2023-10-23  发布在  Shell
关注(0)|答案(4)|浏览(186)

我有下面的bash脚本,我需要采取两个在同一时间。共有8个文件夹中的文件。文件名不连续,如:

file5.txt   file7.txt  file11.txt  file13.txt  file14.txt  file21.txt   file22.txt   file23.txt

我的脚本像:

caulatepet.py \
  --i file5.txt, file7.txt \
  --menscor men-code.list \
  --stat sex-rd.ratio \
  --out ./result/file5_file7.txt

我需要一次输入两个文件(as --i input),比如排列和组合。例如下面的例子:

file5.txt file7.txt
file5.txt file11.txt
file5.txt file13.txt
file5.txt file14.txt
file5.txt file21.txt
file5.txt file22.txt
file5.txt file23.txt

file7.txt file11.txt
file7.txt file13.txt
file7.txt file14.txt
file7.txt file21.txt
file7.txt file22.txt
file7.txt file23.txt
...etc.

我该怎么做?谢谢

watbbzwu

watbbzwu1#

如果我理解正确的话,您试图成对比较文件,而不是比较文件本身(即不将file5.txt与file5.txt进行比较)并且仅将每一对比较一次(即,在将file5.txt与file7.txt进行比较之后,不需要将file7.txt与file5.txt进行比较)。你应该可以通过将文件名存储在数组中,然后在数组上进行双循环来实现:

files=(file5.txt file7.txt file11.txt file13.txt file14.txt file21.txt file22.txt file23.txt)

# for i as each index in the array...
for ((i=0; i<${#files[@]}; i++)); do

    # for j as each index HIGHER THAN i in the array...
    for ((j=i+1; j<${#files[@]}; j++)); do

        caulatepet.py \
          --i "${files[i]}", "${files[j]}" \
          --menscor men-code.list \
          --stat sex-rd.ratio \
          --out "./result/${files[i]%.txt}_${files[j]}"

    done
done

顺便说一句,-i选项的语法看起来很奇怪;在,后面真的应该有一个空格吗?

juzqafwq

juzqafwq2#

TXR Lisp中的解决方案:

$ txr calcpairs.tl
caulatepet.py --i file5.txt, file7.txt --menscor men-code.list --stat sex-rd.ratio --out ./result/file5_file7.txt
caulatepet.py --i file5.txt, file11.txt --menscor men-code.list --stat sex-rd.ratio --out ./result/file5_file11.txt
caulatepet.py --i file5.txt, file13.txt --menscor men-code.list --stat sex-rd.ratio --out ./result/file5_file13.txt
caulatepet.py --i file5.txt, file14.txt --menscor men-code.list --stat sex-rd.ratio --out ./result/file5_file14.txt
caulatepet.py --i file5.txt, file21.txt --menscor men-code.list --stat sex-rd.ratio --out ./result/file5_file21.txt
caulatepet.py --i file5.txt, file22.txt --menscor men-code.list --stat sex-rd.ratio --out ./result/file5_file22.txt
caulatepet.py --i file5.txt, file23.txt --menscor men-code.list --stat sex-rd.ratio --out ./result/file5_file23.txt
caulatepet.py --i file7.txt, file11.txt --menscor men-code.list --stat sex-rd.ratio --out ./result/file7_file11.txt
caulatepet.py --i file7.txt, file13.txt --menscor men-code.list --stat sex-rd.ratio --out ./result/file7_file13.txt
caulatepet.py --i file7.txt, file14.txt --menscor men-code.list --stat sex-rd.ratio --out ./result/file7_file14.txt
caulatepet.py --i file7.txt, file21.txt --menscor men-code.list --stat sex-rd.ratio --out ./result/file7_file21.txt
caulatepet.py --i file7.txt, file22.txt --menscor men-code.list --stat sex-rd.ratio --out ./result/file7_file22.txt
caulatepet.py --i file7.txt, file23.txt --menscor men-code.list --stat sex-rd.ratio --out ./result/file7_file23.txt
caulatepet.py --i file11.txt, file13.txt --menscor men-code.list --stat sex-rd.ratio --out ./result/file11_file13.txt
caulatepet.py --i file11.txt, file14.txt --menscor men-code.list --stat sex-rd.ratio --out ./result/file11_file14.txt
caulatepet.py --i file11.txt, file21.txt --menscor men-code.list --stat sex-rd.ratio --out ./result/file11_file21.txt
caulatepet.py --i file11.txt, file22.txt --menscor men-code.list --stat sex-rd.ratio --out ./result/file11_file22.txt
caulatepet.py --i file11.txt, file23.txt --menscor men-code.list --stat sex-rd.ratio --out ./result/file11_file23.txt
caulatepet.py --i file13.txt, file14.txt --menscor men-code.list --stat sex-rd.ratio --out ./result/file13_file14.txt
caulatepet.py --i file13.txt, file21.txt --menscor men-code.list --stat sex-rd.ratio --out ./result/file13_file21.txt
caulatepet.py --i file13.txt, file22.txt --menscor men-code.list --stat sex-rd.ratio --out ./result/file13_file22.txt
caulatepet.py --i file13.txt, file23.txt --menscor men-code.list --stat sex-rd.ratio --out ./result/file13_file23.txt
caulatepet.py --i file14.txt, file21.txt --menscor men-code.list --stat sex-rd.ratio --out ./result/file14_file21.txt
caulatepet.py --i file14.txt, file22.txt --menscor men-code.list --stat sex-rd.ratio --out ./result/file14_file22.txt
caulatepet.py --i file14.txt, file23.txt --menscor men-code.list --stat sex-rd.ratio --out ./result/file14_file23.txt
caulatepet.py --i file21.txt, file22.txt --menscor men-code.list --stat sex-rd.ratio --out ./result/file21_file22.txt
caulatepet.py --i file21.txt, file23.txt --menscor men-code.list --stat sex-rd.ratio --out ./result/file21_file23.txt
caulatepet.py --i file22.txt, file23.txt --menscor men-code.list --stat sex-rd.ratio --out ./result/file22_file23.txt

代码:

(flow "file*.txt"
  glob
  (csort @1 : (do match `[email protected]` @1
                (toint num)))
  (comb @1 2)
  (each-match ((@f1 @f2) @1)
    (sh `echo caulatepet.py \
        \ --i @f1, @f2 \
        \ --menscor men-code.list \
        \ --stat sex-rd.ratio \
        \ --out \
        \ ./result/@(trim-right ".txt" f1)_@f2`)))

我们可以删除echo来运行程序。
注解代码:

;;; flow: start pipeline with "file*.txt" string
(flow "file*.txt"                       
  ;; glob: produce list of file names matching "file*.txt"
  glob

  ;; caching sort: sort list of names (argument @1) by number.
  ;; (do match ...) produces a function of one argument that
  ;; maps each item @1 to a sort key, which is the file number.
  ;; caching sort means the integer key is calculated only once
  ;; for each file and cached internally by csort.
  (csort @1 : (do match `[email protected]` @1
                (toint num)))

  ;; calculate all two-element combinations of sorted list
  (comb @1 2)

  ;; iterate over combinations, destructuring them as f1 and f2
  (each-match ((@f1 @f2) @1)

    ;; invoke shell command with f1 and f2 inserted via quasistring
    (sh `echo caulatepet.py \
        \ --i @f1, @f2 \
        \ --menscor men-code.list \
        \ --stat sex-rd.ratio \
        \ --out \
        \ ./result/@(trim-right ".txt" f1)_@f2`)))

@1语法出现了几次。它指示在隐式函数中应插入参数1的位置。默认情况下,它被插入在右边;例如,对于glob,我们不需要写(glob @1)

pb3s4cty

pb3s4cty3#

由于您已经在使用Python,我建议您编写一个帮助脚本来生成文件名对组合。幸运的是,Python在itertools包中有一个内置的combinations函数:

import sys
from itertools import combinations

if __name__ == "__main__":
    filenames = sys.argv[1:]
    for pair in list(combinations(filenames, 2)):
        print("\x1F".join(pair))

我们称之为pairs.py。在上面的脚本中,单元分隔符"\x1F"被用作字符串,因为它不可打印,因此不太可能出现在文件名中。这样做是为了简单起见。在生产级代码中,应该使用更好的通信格式(如JSON)。
现在我们可以生成这些对并将它们通过管道传输到脚本中,如下所示:

python pairs.py a.txt b.txt c.txt d.txt | while IFS=$'\x1F' read -r f1 f2; do
    caulatepet.py \
      --i "$f1, $f2" \
      --menscor men-code.list \
      --stat sex-rd.ratio \
      --out "./result/${f1}_${f2}.txt"
done

请注意,我将这两个文件连接到--i选项的单个参数中,因为我认为您的问题中有一个小错误:
--i file5.txt,file7.txt
所有流行的shell(包括bash)都将此序列视为三个单独的参数,大多数传统的CLI参数解析器将其解释为带有file5.txt,值的--i选项,而file7.txt将被解释为单独的参数,这在您的问题中没有意义。

h7wcgrx3

h7wcgrx34#

首先将文件添加到数组中:

for f in *;{ arr+=("$f"); }

而不是像这样循环它:

for ((i=0,j=1; i<${#arr[@]}; i+=2,j+=2));{ echo ${arr[i]} ${arr[j]}; }

测试结果:

file1.txt file2.txt
file3.txt file4.txt

相关问题