Unix 명령을 사용하여 서로 다른 폴더에 있는 유사한 이름을 가진 여러 파일을 병합하는 방법은 무엇입니까?

Unix 명령을 사용하여 서로 다른 폴더에 있는 유사한 이름을 가진 여러 파일을 병합하는 방법은 무엇입니까?

나는 이 질문을 이전에 요청하고 답변한 적이 있다는 것을 알고 있습니다. 코드를 시도했지만 올바른 출력을 얻지 못했습니다.

vanila1과 vanila2라는 2개의 폴더가 있습니다. 각 폴더에는 비슷한 이름을 가진 400개의 파일이 있습니다.

ls vanila1
MB.2613.007_0021.ED4_KS1A29-7_338_all
MB.2613.007_0022.ED9_SD2A27-1_180_all
MB.2613.007_14.ED14_IA2A35-2_310_all

ls vanila2
MB.2613.007_0021.ED4_KS1A29-7_338_all
MB.2613.007_0022.ED9_SD2A27-1_180_all
MB.2613.007_14.ED14_IA2A35-2_310_all

동일한 이름을 가진 파일을 병합하고 싶습니다. 다음을 사용하고 있습니다.

ls vanila1 | while read FILE; do
  cat vanila1/"$FILE" vanila2/"$FILE" >> all_combined/"$FILE"
done

올바른 출력이 나오지 않습니다. 결합된 파일의 줄 수가 file1과 file 2의 합보다 큽니다. 내가 뭐 잘못 했어요?

답변1

아마도 루프를 여러 번 실행하고 있을 것 같습니다. >>리디렉션 연산자를 사용하고 있으므로추가결과 파일은 매번 커집니다.

대신에(저는 여기서도 사용하지 않습니다 ls. "왜 `ls`를 구문 분석하지 *않나요*?"이유로):

for name in vanila1/*; do
    base_name=${name##*/}

    if [ -f "vanila2/$base_name" ]; then
        cat "$name" "vanila2/$base_name" >"all_combined/$base_name"
    else
        printf 'No file in vanila2 corresponds to "%s"\n' "$name" >&2
    fi
done

변수 대체는 ${name##*/}경로 이름 vanila1/MB.2613.007_0021.ED4_KS1A29-7_338_all을 로 변환합니다. 즉 , 슬래시(경로 이름의 파일 이름 구성 요소 또는 "기본 이름")를 포함하여 MB.2613.007_0021.ED4_KS1A29-7_338_all그 앞의 모든 것을 제거합니다 . /이 제품은 교체될 수 있습니다 $(basename "$name").

vanila2에서 가져온 이름에 해당하는 파일이 에 있으면 vanila1두 파일이 연결되어 all_combined해당 디렉터리에 배치됩니다. 그렇지 않은 경우 이 사실에 대한 진단 메시지가 나타납니다.

>대신 을 사용하면 이름이 같은 >>기존 all_combined파일이 추가되는 대신 대체됩니다.


당신이 가지고 있다면다른 파일들또는 디렉토리 인 경우 관심 있는 파일(예: 또는 유사한 파일) 만 일치하도록 vanila1루프의 패턴을 수정할 수 있습니다 .vanila1/*vanila1/*_all

답변2

그렇다면 두 디렉터리에 같은 이름을 가진 파일이 있는데, 두 파일을 연결할 수 있는 두 파일은 어디에 있습니까?

for file in dir1/*; do
   otherfile="$(basename "$file")"
   if [[ -r dir2/"${otherfile}" ]]; then
       cat "$file" dir2/"$otherfile" >> combined/"$otherfile"
   fi
done

관련 정보