파일 이름의 숫자를 줄이기 위해 여러 파일의 이름을 바꾸시겠습니까?

파일 이름의 숫자를 줄이기 위해 여러 파일의 이름을 바꾸시겠습니까?

-1에 의해 동기화되지 않은 파일 이름이 잘못되었습니다. 문제는 그 중 1000개의 이름을 바꿔야 한다는 것입니다.

  • DBGC180_805754
  • DBGC180_805755
  • DBGC180_805756

에게

  • DBGC180_805753
  • DBGC180_805754
  • DBGC180_805755

나는 bash 스크립트나 unix 명령을 사용하는 것을 선호합니다.

답변1

다음을 수행할 수 있습니다.

# {smallestfilenum..largestfilenum}

for i in {805754..999999}; do 
   mv "DBGC180_$i" "DBGC180_$(($i-1))";
done

작은 숫자(예: 805754..805758)를 사용해 예상대로 작동하는지 확인하세요. 새 이름의 파일이 이미 존재하는 경우 덮어쓰게 된다는 점에 유의하세요.

답변2

  1. 이름을 바꾸려는 파일을 하위 디렉터리로 이동합니다(이름을 변경하지 않고).
  2. 하위 디렉터리의 파일 이름을 원래 디렉터리로 바꿉니다.

1단계를 권장하지 않는 데에는 두 가지 이유가 있습니다. 비록 1단계 없이도 가능하더라도 다음과 같습니다.

  • 명령이 중단되면 중단한 부분부터 다시 시작할 수 있습니다. 어떤 파일의 이름이 이미 바뀌었고 어떤 파일은 변경되지 않았는지 즉시 알 수 있기 때문입니다.
  • 잘못된 순서로 이름을 바꾸거나 기존 파일 중 하나를 덮어쓰는 것에 대해 걱정할 필요가 없습니다.

테스트되지 않은 쉘 조각(감소할 숫자에 앞에 0이 붙지 않는다는 사실에 의존함):

mkdir to_decrement
for x in DBGC180_80575[4-9] DBGC180_8057[6-9]? DBGC180_805[8-9]?? DBGC180_80[6-9]??? DBGC180_8[1-9]???? DBGC180_9?????; do
  mv "$x" to_decrement/
done
cd to_decrement
for x in *; do
  number="${x##*_}"
  mv -i -- "$x" "../${x%_*}_$((number-1))"
done
cd ..
rmdir to_decrement

와 함께zsh, 덕분에 이 작업을 훨씬 더 간단하게 만들 수 있습니다.숫자 범위 글로브, 그것은내장mv이는 명령줄 길이 제한에 부딪히는 것을 방지하고패턴 기반 대량 이름 변경 기능. zsh에서:

autoload -U zmv
zmodload -m -F zsh/files b:zf_\*
mkdir to_decrement
zf_mv DBGC180_<805754-> to_decrement/
zmv 'to_decrement/(*)_(*)' '${1}_$(($2-1))'
rmdir to_decrement

답변3

DBGC180_805754따라서 이름 을 DBGC180_805753, ...55to ...54등 으로 바꾸고 싶습니다 . 그것이 바로 제가 다루게 될 문제입니다.

먼저 이 스크립트를 의 어딘가에 넣고 PATH이름을 waltinator.

#!/bin/bash
#step through the parameters 
while [[ -n "$1" ]] ; do
    oldname="$1"
    # shift the arguments left
    shift;
    # strip off the fixed part of the old name
    oldnum=${oldname##DBGC180_}
    # decrement the number (this is what was wanted, right?)
    newnum=$(( $oldnum - 1 ))
    # build the new, improved filename
    newname="DBGC180_$newnum"
    if [[ -f "$newname" ]] ; then
        printf "Cannot rename $oldname to $newname, $newname exists.\n" >&2
        exit 1
    fi
    mv --no-clobber "$oldname" "$newname"
done
exit 0

다음 단계에서는 스크립트가 에 있고 $HOME/bin/waltinator가 있다고 가정합니다 chmod +x $HOME/bin/waltinator.

find . -type f -name 'BDGC180_[0-9][0-9][0-9][0-9][0-9][0-9]` -print | \
    sort | \
    xargs $HOME/bin/waltinator

find이름이 쉘 glob 패턴 " BDGC180_뒤에 6자리( )와 일치하는 파일(특정 순서 없음)을 찾습니다 [0-9]. 정렬된 목록을 원하므로( 이름을 바꾸기 전에 ...97로 이름을 바꾸면 실패할 수 있음) through 의 출력을 실행합니다 . 그런 다음 (정렬된) 파일 이름 목록을 가져와 (정렬된) 파일 이름 목록을 에 전달하는 명령을 작성합니다 . 인수 목록을 줄여야 하는 경우 읽으십시오....96...96findsortxargs$HOME/bin/waltinatorman xargs

그 문제에 대해서는 다음을 읽으십시오.

for page in bash mv find sort xargs ; do
    man "$page"
done   

답변4

rename각 숫자를 마이너스 1로 대체하는 데 사용됩니다 .

$ rename -v 's/\d{6}/sprintf("%06",($&-1))/e'    

노트

  • renamePerl 표현식을 사용하여 파일 이름을 바꿉니다.
  • srename정규식 패턴과 일치하는 파일 이름 중 일부 또는 전부를 대체할 항목을 지정합니다 .
  • Perl 대체 표현식은 다음과 같이 구성됩니다.
    • s/PATTERN/REPLACEMENT/MODIFIER
  • \d{6}rename검색하고 대체할 패턴입니다 . 이는 십진수 6자리입니다.
  • $일치하는 하위 문자열을 저장하는 변수입니다 \d{6}(이 경우 "하위 문자열"은 int입니다).
  • sprintf("%06",($&-1))에 저장된 값을 검색하여 $감소시킨 다음 이 값을 대체 값으로 반환합니다. 선행 0을 처리하기 위해 존재 %06합니다.
  • erenamePerl 문인 것처럼 대체를 평가하고 해당 반환 값을 대체 텍스트로 사용하도록 지정됩니다 .
  • -vrename무엇을 하고 있는지 에코 합니다 .

더욱 안전해지기를 원한다면 플래그를 사용하여 플래그를 사용하는 -n대신 rename수행할 작업만 알려주십시오.

이는 감소에만 작동하는 것으로 보이므로 주의해서 처리하십시오.

관련 정보