Bash 전달 입력

Bash 전달 입력

저는 오픈 소스 도구를 사용하여 파일을 게놈 범위(R 언어 기능 "병합"과 기능적으로 유사)로 병합하고 있습니다. 소프트웨어는 한 번에 두 개의 파일만 가져올 수 있습니다. 두 개 이상의 파일을 병합해야 하는 경우 강제로 이 작업을 수행해야 한다고 가정해 보겠습니다.

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

병합하려는 파일(모두 다른 폴더에 있음)의 경로가 포함된 별도의 파일이 있습니다. 명령을 실행할 때 명령의 출력이 다시 입력으로 제공되도록 이 명령을 어떻게 작성할 수 있습니까?

답변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"

문서에는 입력 파일이 하나만 주어지면 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"

이는 파일에서 한 줄씩(예: 파일 이름)을 읽고 file_of_filenames 해당 파일 이름과 이전 출력 실행을 사용하여 새 출력 파일을 생성합니다. 출력 파일의 이름이 입력 파일로 바뀌고 루프가 계속됩니다. cgatools$tmpfile.out$tmpfile.in

시작을 처리하기 위해 첫 번째 파일 이름 줄을 개별적으로(변수로 firstfilename) 읽고 파일을 입력 파일에 복사하여 결합할 파일이 2개가 되도록 합니다. 모든 명령이 "()" 내에 있으므로 첫 번째 읽기가 중단된 부분부터 while 루프 내 읽기가 계속됩니다.

관련 정보