Bash 転送入力

Bash 転送入力

私はオープンソースツールを使用してファイルをゲノムスコープ(R言語機能「マージ」と機能的に似ています)にマージしています。ソフトウェアは一度に2つのファイルしかインポートできません。複数のファイルをマージする必要がある場合は、強制的にこれを行う必要があるとします。

mytempdata = join  mydata1 + mydata2
mytempdata = join  mytempdata + mydata3
.
.
.
mytempdata = join  mytempdata + mydata(n)

マージしたいファイル(すべて別のフォルダにあります)へのパスを含む別のファイルがあります。コマンドを実行すると、コマンドの出力が再入力として提供されるように、このコマンドをどのように作成できますか?

答え1

ファイルに1行に1つのファイルが含まれていると仮定すると、次のような醜い操作を実行できます。

tool="cgatools join --beta --match <specification> --overlap <overlap_spec> --select <output_fields> --always-dump --output-mode compact --input"

{
    read -r filename
    cmd="cat \"$filename\""
    while read -r filename; do
        cmd+=" | $tool \"$filename\""
    done
} < file_of_filenames

cmd+=" > output_file"

echo "$cmd"
eval "$cmd"

ドキュメントには、入力ファイルが1つしか与えられていない場合はstdinから別のファイルを読み込み、--outputオプションが指定されていない場合はstdoutが使用されます。


テストされていませんが、これも機能できます(bash)

# declare the cgatools command with options
# stored in a shell array.
cga_join=( 
    cgatools join --beta 
                  --match "specification"
                  --overlap "overlap_spec" 
                  --select "output_fields"
                  --always-dump 
                  --output-mode compact 
)

# the entry point to the join process
# shift the first argument off the list of arguments, and
# pipe its contents into the recursive call
call_join() {
    local first=$1
    shift
    cat "$first" | call_join_recursively "$@"
}

# recursively call "cgatools join"
# input will be read from stdin; output goes to stdout
# if this is the last filename to join, pipe the output through "cat"
# otherwise pipe it into another call to this function, passing the 
# remaining filenames to join.
call_join_recursively() {
    local file=$1
    shift
    local next_command=(cat)
    if [[ $# -gt 0 ]]; then
        next_command=( "$FUNCNAME" "$@" )
    fi
    "${cga_join[@]}" --input "$file" | "${next_command[@]}"
}

# read the list of filenames to join.
# stored in the "filenames" array 
mapfile -t filenames < file_of_filenames

# launch the joining, passing the filenames as individual arguments.
# store the output into a file.
call_join "${filenames[@]}" > output_file

答え2

次の簡単な反復ソリューションを探していると思います。

#!/bin/sh
( tmpfile=/tmp/result
  read firstfilename
  cat "$firstfilename" >$tmpfile.in
  while read filename
  do cgatools join \
          --beta \
          --input $tmpfile.in "$filename" \
          --match <specification> \
          --overlap <overlap_spec> \
          --select <output_fields> \
          --always-dump \
          --output-mode compact  >$tmpfile.out
     mv $tmpfile.out $tmpfile.in
  done
) < file_of_filenames
echo "result is in $tmpfile.in"

これはファイルから1行ずつ(ファイル名など)を読み取り、file_of_filenames そのファイル名と古い出力実行を使用して新しい出力ファイルを生成します。出力ファイルの名前が入力ファイルに変更され、ループが続行されます。 cgatools$tmpfile.out$tmpfile.in

開始を処理するために、最初のファイル名行を個別に(変数としてfirstfilename)読み込み、ファイルを入力ファイルにコピーして、結合するファイルが2つになるようにします。すべてのコマンドが「()」内にあるため、最初の読み取りが中断されてからwhileループ内の読み取りが続行されます。

関連情報