Bash - 입력 번호로 시작하는 숫자로 정렬된 파일 이동/이름 바꾸기

Bash - 입력 번호로 시작하는 숫자로 정렬된 파일 이동/이름 바꾸기

다음과 같은 파일 번호 목록이 있습니다.

01_file_name.log
01_file_name.txt
02_file_name.log
02_file_name.txt
03_file_name.log
03_file_name.txt
04_file_name.log
04_file_name.txt
05_file_name.log
05_file_name.txt

03*모든 파일 에 04*새 파일을 삽입하고 싶습니다 . 따라서 와드 번호부터 시작하여 03모든 파일을 이동/이름 변경해야 하며 앞에 오는 번호를 2씩 늘려야 합니다. 따라서 목록은 다음과 같습니다.

01_file_name.log
01_file_name.txt
02_file_name.log
02_file_name.txt
05_file_name.log
05_file_name.txt
06_file_name.log
06_file_name.txt
07_file_name.log
07_file_name.txt

나는 다음과 같은 것을 생각하고 있습니다. bash script.sh 03 02while 03$1시작할 파일 이름의 번호와 추가할 번호입니다 02. $2중첩을 통해 이를 달성하려고 했지만 루프가 와드에서 지정된 번호의 파일만 실행하도록 하기 위해 for-loop카운터를 사용하는 조합을 포기해야 했습니다 .((++))

답변1

이것이 당신이 원하는 것입니다. 한 가지: BASH에서만 작동하는 것 같아요. MAXDIGITS선택 사항이므로 세 자리 이상을 사용해야 하는 경우를 대비해 넣었습니다. 사용하지 않는 경우 해당 줄을 삭제하세요.

    #!/bin/bash

    BOTTOM=$1
    SHIFT=$2
    MAXDIGITS=0$3
    for filename in $(ls -r *.{txt,log}); do
        PREFIX=${filename%%_*}
        NEWPREFIX=$(expr $PREFIX + $SHIFT)
        if [ $PREFIX -ge $BOTTOM ]; then
            NEWPREFIX=$(printf %${MAXDIGITS}d $NEWPREFIX)
            mv $filename ${NEWPREFIX}_${filename#*_}
        fi
    done

지침:

    ./myscript <BOTTOM> <SHIFT> <MAXDIGITS>
    ### Example:
    ./miscript 03 02 2 #This means "Start at 03_filename.*, shift the prefixes by 2 and use 2 digits to construct the new prefixes".

동일한 디렉터리에 동일한 구문(prefix_filename.{txt,log})을 따르지 않는 다른 파일이 있는 경우 필터링해야 합니다. 그리고 접두사와 파일명을 구분하기 위해 "_"를 사용했기 때문에 이를 변경하면 코드를 수정해야 합니다.

답변2

그만한 가치가 있기 때문에 이것은 bash두 가지가 포함된 하나의 라이너 입니다.프로세스 교체매우 간단한 awk프로세스입니다.

$ ls -r -1 *_file_name.{txt,log}    # list initial files in reverse order
05_file_name.log
05_file_name.txt
04_file_name.log
03_file_name.txt
03_file_name.log
03_file_name.txt
02_file_name.log
02_file_name.txt
01_file_name.log
01_file_name.txt

$ source <(awk 'BEGIN{FS="_"} $1>2 {prefix=$1+2; printf ("mv -f %s %0.2d_%s_%s\n",$0,prefix,$2,$3)}' <(ls -r -1 *_file_name.{log,txt}))

$ ls -1 *_file_name.{txt,log}     # list resulting files
01_file_name.log
01_file_name.txt
02_file_name.log
02_file_name.txt
05_file_name.log
05_file_name.txt
06_file_name.log
06_file_name.txt
07_file_name.log
07_file_name.txt

설명하다:

위의 줄은 오른쪽에서 왼쪽으로 읽거나 적어도 "이해"됩니다.

  • ls -r -1 *_file_name.{log,txt} 처리할 모든 파일을 1열 형식으로 역순으로 나열합니다.
    파일 접두사(기호로 표시 *)에 숫자가 아닌 문자가 포함되어 있으면 예상치 못한/원치 않는 결과가 발생할 수 있습니다. 이를 방지하려면 이 단계에서 처리할 파일을 필터링하세요.

  • <(...)공예 대체. 파일 설명자, 명명된 파이프라는 특수 임시 파일을 사용하여 이전 결과 출력을 참조할 수 있습니다. 자세한 내용은 man bash터미널에 게시하세요 .

  • awk스크립트:

    • BEGIN{FS="_"} 레코드 처리를 시작하기 전에 레코드의 필드 구분 기호를 "_"(awk의 첫 번째 블록)로 설정하세요.
    • awk두 번째 블록의 조건 $1>2: 파일 이름 접두사가 2보다 엄격하게 큰 레코드만 처리합니다.
    • prefix=$1+2awk의 "접두사" 내부 변수를 정의합니다. 접두사 $1+ 2 와 수치적으로 동일하게 만듭니다 .
    • printf("my_format",var1,var2,...)줄 바꿈으로 구분된 인쇄 형식 지정 명령입니다. 형식 지정에는 %0.2d변수 "접두사"를 awk두 자리 숫자로 인쇄하고 필요한 경우 0을 채우는 작업이 포함됩니다. 출력은 다음과 같습니다
      mv -f 05_file_name.log 07_file_name.log
      mv -f 05_file_name.txt 07_file_name.txt
      mv -f 04_file_name.log 06_file_name.log
      mv -f 04_file_name.txt 06_file_name.txt
      mv -f 03_file_name.log 05_file_name.log
      mv -f 03_file_name.txt 05_file_name.txt
  • 정렬된 출력을 다른 파일(두 번째 프로세스 교체)로 처리하고 명령을 실행하도록 합니다 mv -f ....

왜 재사용하는지 궁금하시다면인바운드 또는 아웃바운드 프로세스 교체(POSIX가 아닙니다!) in bash이 유리합니다.이것예를 들어.

최종 참고사항:

위의 코드 줄에 런타임 매개변수를 포함하고 이를 실행 가능한 셸 스크립트에 캡슐화하는 것은 쉽습니다. 정의 VAR1하고 VAR2할당하는 프로세스부터 시작하세요 awk.

$ source <(awk -v VAR1=2 -v VAR2=2 'BEGIN{FS="_"} $1>VAR1 {prefix=$1+VAR2; printf ("mv -f %s %0.2d_%s_%s\n",$0,prefix,$2,$3)}' <(ls -r -1 *_file_name.{log,txt}))

실행 가능한 스크립트에서 script.sh:

$ cat script.sh
#!/usr/bin/bash
if [ "$#" -eq 2 ] ; then
    source  <(awk -v VAR1=$1 -v VAR2=$2 'BEGIN{FS="_"} $1>VAR1 {prefix=$1+VAR2; printf ("mv -f %s %0.2d_%s_%s\n",$0,prefix,$2,$3)}' 
              <(ls -r -1 *_file_name.{log,txt})
             )
    exit 0
else
    echo "   Usage: script.sh VAR1 VAR2.\n    Abort execution (exit code 1)."
    exit 1
fi

여기서 VAR1VAR2OP에 정의된 의미가 있습니다. 프로덕션 환경에서 이 스크립트를 사용해야 하는 경우 입력 파일 및 변수의 값이 항상 예상되는지 확인하기 위해 많은 검사와 안전 장치를 추가하는 것이 좋습니다.

for@MarceloCastro의 스크립트는 훌륭하지만 가능하면 피하는 경향이 있는 루프를 기반으로 합니다 . for루프는 느린 경향이 있습니다. 루프를 작업하면 이를 알 수 있습니다.파일 수.

답변3

나는 당신의 목표에 맞게 이 스크립트를 만들었습니다.

for files in *.extensions
do
  num=$(echo "$files" | awk '{print $1}' | cut -c1-2)
  if [ $num -gt 2 ]; then
     AS=$((num+2))
     temp=$(echo "$files" | cut -c 3-)
     mv $files 0$AS"$temp"
  fi
done

답변4

그리고 zsh:

$ autoload zmv
$ zmv -n -f '(<3->)(_*)(#qnOn)' '${(l:2::0:)$(($1+2))}$2'
mv -- 05_file_name.txt 07_file_name.txt
mv -- 05_file_name.log 07_file_name.log
mv -- 04_file_name.txt 06_file_name.txt
mv -- 04_file_name.log 06_file_name.log
mv -- 03_file_name.txt 05_file_name.txt
mv -- 03_file_name.log 05_file_name.log

그런 다음 실제로 이 작업을 수행하려면 제거 -n(모의 실행을 위해)하십시오.

  • zmv pattern replacement: zmv강력한 zsh glob 및 Spread 연산자를 활용하여 복잡한 파일 이름 바꾸기를 수행하는 자동 로드 가능 기능입니다.
  • <x-y>10진수 x와 y를 일치시킵니다.
  • (#q...)글로벌 예선
  • nOn: ame의 n숫자 rder o(대문자 O로 반전) n. 따라서 숫자를 늘리고 있으므로 05...필요에 따라 그보다 먼저 올 것입니다.04...
  • ${(l:n::padding:)expansion}: l패드 길이 연장N사용충전재. 따라서 ${(l:2::0:)}사용시 길이는 0~2로 유지한다.
  • $(($1+2)), 첫 번째 캡처된 그룹은 2씩 증가합니다.
  • $2:두 번째 캡처 그룹: 선행 숫자 뒤에 오는 내용입니다.

관련 정보