Bash는 파일 쌍을 반복합니다.

Bash는 파일 쌍을 반복합니다.

비슷한 이름을 가진 여러 파일이 포함된 디렉토리가 있는데 a04x.txt각각 해당 b04y.txt파일이 있습니다. 각 파일 쌍에 대해 몇 가지 명령을 실행하고 c04z.txt각 쌍에 대해 추가 파일을 생성할 수 있어야 합니다 .

파일의 실제 숫자는 상당히 크고 희박하므로 1부터 99까지의 모든 숫자 또는 이와 유사한 숫자를 단순히 반복하는 것은 작동하지 않습니다.

현재 나는 작업을 처리하기 위해 다음 접근 방식을 사용하지만 이를 수행하는 데 더 짧고 더 나은 방법이 있어야 할 정도로 일반적인 작업인 것 같습니다.

for num in ./a*x.txt
do
  num="${num##*/a}"
  num="${num%x.txt}"

  my_command a${num}x.txt b${num}y.txt c${num}z.txt
done

a${num}x.txt이상적으로는 b${num}y.txt동일한 번호의 일치하는 파일이 있거나 파일이 없을 때 경고를 받고 싶습니다. 또한 파일 세트를 파이프로 연결 xargs하거나 parallel동시에 여러 파일 세트를 처리할 수 있는 쉬운 방법을 원합니다 .

더 좋은 방법이 있나요?

답변1

GNU Parallel에는 이를 수행하는 방법이 있으며 보너스로 명령을 병렬로 실행합니다.

$ parallel my_command {} \
                      {= s/a([0-9]+)x.txt/b\1y.txt/ =} \
                      {= s/a([0-9]+)x.txt/c\1z.txt/ =} \
           ::: a*x.txt

이러한 대체품은 Perl 코드입니다. 줄 바꿈은 단지 가독성을 위한 것입니다. 한 번에 한 줄씩 표시됩니다.

답변2

  1. 한 가지 방법은 다음과 같습니다

    for afile in a*x.txt
    do
        bfile=${afile/a/b}; bfile=${bfile/x.txt/y.txt}
        cfile=${afile/a/c}; cfile=${cfile/x.txt/z.txt}
    
        my_command "$afile" "$bfile" "$cfile"
    done
    

    나는 이것이 큰 개선이라고 생각하지 않으며 처럼 사용할 때 큰 개선이 아니라고 생각 afoox.txtbarx.txt합니다. 또한 이것은 다른 POSIX 호환 셸에서는 작동하지 않을 수 있습니다( ##POSIX에서 지정한 것과는 다릅니다). .%

  2. 이렇게 말하면 쉽죠

        if [ -f "$bfile" ]
        then
            my_command "$afile" "$bfile" "$cfile"
        else
            echo Error
        fi
    

    파일 예외를 포착합니다 a(예: a17x.txt해당 예외가 없음 b17y.txt).

  3. 당신이 넣으면

    for afile               # with no list, defaults to "$@"; i.e., the script’s arguments
    do
        bfile=${afile/a/b}; bfile=${bfile/x.txt/y.txt}
        cfile=${afile/a/c}; cfile=${cfile/x.txt/z.txt}
    
        if [ -f "$bfile" ]
        then
            my_command "$afile" "$bfile" "$cfile"
        else
            echo Error
        fi
    done
    

    그런 다음 파일 이름 목록을 인수로 사용하여 스크립트를 실행하면 해당 스크립트가 처리됩니다. 그런 다음 또는 를 통해 스크립트를 실행할 수 있습니다.anumx.txtxargsparallel

  4. 위 프로세스의 일부로 b파일 이상값(예: b42y.txt 해당 항목 없음 )을 확인하는 a42x.txt것은 쉽지 않지만 별도의 루프에서 수행하는 것은 쉽습니다.

    for bfile in b*y.txt
    do
        afile=${bfile/b/a}; afile=${afile/y.txt/x.txt}
        if [ ! -f "$afile" ]
        then
            echo Error
        fi
    done
    

관련 정보