파일 이름 충돌 없이 파일 배치에서 문자열 찾기 및 바꾸기

파일 이름 충돌 없이 파일 배치에서 문자열 찾기 및 바꾸기

나는 수년에 걸쳐 수집된 무작위이고 쓸모없는 파일 이름을 가진 수천 개의 파일을 포함하는 디렉토리 트리를 가지고 있습니다.

나는 그것들을 정리하고 관련성을 유지하고 특정 단어를 제거하고 싶지만 중복된 파일 이름을 생성하지 않기를 원합니다.

예를 들어

WONDERBROS - PAWG Remy LaCroix Gets BREAKFAST! (pwg11717) - SOMENAME.mp4

다음과 같은 이름으로 바꾸고 싶습니다.

WONDERBROS.PAWG.Remy.LaCroix.Gets.BREAKFAST!.(pwg11717).mp4

그래서 몇 가지 포인트가 있어요

  • 모든 공백을 다음으로 바꾸십시오..
  • SOMENAME이 나타날 때마다 삭제하세요.
  • 이름을 바꾸기 전에 파일 이름이 이미 존재하는지 확인하고, 숫자가 추가되면 아무것도 덮어쓰지 않도록 고유한 파일 이름이 될 때까지 계속 시도하세요.

쉘 스크립트를 통해서도 가능할 것 같은데, 추천하는 도구가 있다면 그것도 시도해 보고 싶습니다.

비슷한 것을 시도했지만 첫 번째 줄만 작동하는 것 같습니다.

# find and replace spaces with .
find /home/matt/rename_test_tmp/ -depth -name "* *" -execdir rename 's/ /./g' "{
# find and replace somename with .
find /home/matt/rename_test_tmp/ -depth -name "somename" -execdir rename 's/ 
# find and replace SOMENAME
find /home/matt/rename_test_tmp/ -depth -name "SOMENAME" -execdir rename 's/ 
# find and replace Somename
find /home/matt/rename_test_tmp/ -depth -name "Somename" -execdir rename 's/ 

내 문제는 내가 아직도 reg ex를 이해하지 못한다는 것입니까?

답변1

이것이 기본 구조입니다. 문제가 발생하면 MAXTRYS는 이름 바꾸기를 중지합니다. 합리적인 값을 선택하십시오.

#!/bin/bash
#
# Usage: 
#       numberedMove xy-file.txt TARGETDIR 
#
file="$1"
targetDir="$2"
MAXTRYS=666
#
# @TODO
# add tests for permissions, maybe handle symlinks etc.
#
test -f "$file" || {
    echo No such file "$file" or not an ordinary file
    exit 1;
}

test -d "$targetDir" || {
    echo No such directory "$targetDir"
    exit 2;
}

#
# append NUM+1 to filename, to create unique name
#
numbered () {
  fname="$1"
  num=$2
  if [[ $num -gt $MAXTRYS ]]
  then
    echo " giving up - max trys: $MAXTRYS "
    exit 3
  fi
  # echo "mv $fname → $targetDir/$fname$num"
  test -f "$targetDir/$fname$num" && numbered "$fname" $((num+1)) || mv "$file" "$targetDir/$fname$num"
}

#
# remove all SOMENAME and replace every blank with a dot
#
filtername () {
   fname="$1"
   fname=${fname//SOMENAME/}
   fname=${fname// /.}
   echo "$fname"
}
#
# filter filename, if unique: move, else move with number suffix
#
if [[ -e "$file" ]]
then
    newname=$(filtername "$file")
    if [[ ! -f "$targetDir/$newname" ]]
    then
        # echo "mv $file → $targetDir/$newname"
        mv "$file" "$targetDir/$newname"
    else
        # echo "mv $file → $targetDir/$newname NUMBERED"
        numbered "$newname" 1
    fi
fi

더 많은 규칙을 추가하고 기존 규칙을 변경할 수 있습니다 filtername.

이것이 내 자신의 필요를 위한 것이라면 점은 상당히 약한 표시기(a.tar.bz2)이기 때문에 공백을 "." 대신 "-"로 바꿀 것입니다.

대신 여러 구분 기호를 하나로 축소합니다.

    mv "ab cd - SOMENAME..mp3" → "./B/ab.cd.-...mp3" 
    mv "ab cd - SOMENAME..mp3" → "./B/ab-cd-.mp3" 

파일 확장자를 유지하고 마지막 확장자 앞에 숫자를 넣습니다.

    mv "ab cd- SOMENAME..mp3"  → "./B/ab-cd-0.mp3" 
    mv "ab cd - SOMENAME..mp3" → "./B/ab-cd-1.mp3" 
    mv "ab cd -SOMENAME..mp3"  → "./B/ab-cd-2.mp3" 

많은 프로그램이 확장 기능을 해석하기 때문입니다.

약 10개의 파일로만 프로그램을 테스트했기 때문에사용 전 백업을 해주세요, 작업이 성공했는지 확인합니다(총 파일 크기 및 파일 수를 통해 가능).

내 테스트:

for f in a* ; do ./numberedMove.sh "$f" ./B ; done

프로그램을 CWD에 배치하면 자체적으로 이동할 수 있다는 점에 유의하세요.

답변2

Perl 이름 바꾸기 유틸리티를 사용하는 경우 다음을 시도해 보십시오.

find . -type f -execdir rename -n 's/\s*-\s*/./g; s/\s+/./g; s/somename//ig' {} +

성냥이 둘러싸여 \s*-\s*있습니다-- 이상의 공백 문자(즉, -선택적 공백이 있는 문자) \s+성냥하나- 또는 그 이상의 공백 문자.

s/search/replace/이름 바꾸기 스크립트에 필요한 만큼 명령을 추가할 수 있습니다. 그러나 실행 순서에 주의를 기울여야 합니다. 예를 들어 "foo"를 "bar"로 변경하고 "food"를 "drink"로 변경하려면 다음이 필요합니다.s/food/drink/ 앞으로 s/foo/bar/후자가 food되기 때문이다 bard.

위 명령은 모든 파일 이름에 적용됩니다. 일부 s/search/replace/명령이 특정 파일 이름에 대해 작동하지 않는 경우 이는 오류가 아닙니다. 해당 특정 명령은 적용되지 않습니다(그러나 다른 명령은 계속 적용됩니다). 그럼에도 불구하고 특정 이름 바꾸기를 특정 파일 이름에만 적용하려면 find또는 조건자를 사용하여 여러 명령을 실행해야 할 수도 있습니다.-name-iname

여러 단어를 동일한 대체 단어로 변경하려는 경우 대체를 사용할 수도 있습니다. 예를 들어

s/(somename|someothername|thisname|thatname)//ig

모두 빈 문자열로 변경합니다(즉, 삭제). 수정자는 /i대소문자를 구분하지 않습니다.

-n옵션은 rename시험 실행 옵션입니다.회의이름이 바뀌었지만 실제로는 아무것도 이름이 바뀌지 않습니다. -n이름 바꾸기 명령이 원하는 작업을 수행하고 원하지 않는 작업을 수행하지 않는다는 것을 확인한 후 이름 바꾸기 명령에서 해당 명령을 제거하십시오. 이름을 바꿀 때 자세한 출력을 원하면 -n를 바꾸십시오 -v.

에서 man rename:

-v,-verbose

Verbose: 성공적으로 이름이 변경된 파일의 이름을 인쇄합니다.

-n,-nono

작업 없음: 이름을 바꿀 파일 이름을 인쇄하지만 이름을 바꾸지는 않습니다.


노트: Perl 유틸리티는 새 파일 이름이 이미 존재하는 경우 rename파일 이름을 바꾸지 않습니다 . 충돌이 발생할 경우 파일 이름에 숫자를 추가하는 기능이 내장되어 있지 않지만 이 이름 바꾸기의 가장 좋은 기능 중 하나는 간단한 작업에만 국한되지 않는다는 것입니다. 예를 들어 다음을 s/search/replace/실행할 수 있습니다.어느스크립트에서 Perl 코드의 이름을 바꾸면 소스 파일 이름이 변경된 이름으로 변경됩니다( $_명시적 변수 이름을 사용하지 않으면 s///또는 y//암시적으로 같은 연산자가 수정됩니다. 여기에 새로운 설명이 있습니다.$_perl$_https://perlmaven.com/the-default-variable-of-perl).

이것은 다음과 같은 것을 허용합니다(테스트되지 않았지만 작동할 수 있음)

find . -type f -execdir rename -n '
    s/\s*-\s*/./g; 
    s/\s+/./g;
    s/somename//ig;

    if (-f $_) {
      my $num='001';
      while (-f "$_.$num") {
        $num=sprintf('%03i',++$num);
      };
      $_ = "$_.$num";
    }' {} +

파일 이름이 이미 존재하는 경우 파일 이름에 0으로 채워진 3자리 숫자를 추가해야 합니다(예: from 001~ ). 두 자리 숫자( to )만 필요한 경우 sprintf 에서 로 999변경하세요 %03i. 또는 중복된 파일에 두 개 이상의 숫자가 포함되지 않도록 하려면 이를 just로 변경한 다음 while 루프 내에서 no를 사용하세요.%02i01999my $num=1$num++sprintf()

조금 더 작업하면(파일 이름을 "기본 이름"과 "확장자" 부분으로 분할하여) 확장자 끝에 추가하는 대신 확장자 앞에 번호를 삽입할 수 있습니다.


rename이 옵션을 사용하면 현재 사용 중인 버전을 확인할 수 있습니다 -V. 예를 들어, 내 Debian 시스템에서 renameperl 이름 바꾸기는 다음과 같은 반면 rename.ulutil-linux 이름 바꾸기는 다음과 같습니다.

$ rename -V
/usr/bin/rename using File::Rename version 0.20

$ rename.ul -V
rename.ul from util-linux 2.31.1

답변3

find . -maxdepth 1 -type f > orginal_file

find . -maxdepth 1 -type f -exec sed -r "s/\s+//g"| sed "s/SOMENAME//g" >> /var/tmp/modified file

paste orginal_file /var/tmp/modified file >> combined_orginal_modified_column_wise

for i in `cat /var/tmp/modified file`
do
if [[ -f $i ]]
then
echo "file exsist"
else
awk -v i="$i" '/i/{print "mv" " " $1 " " $2}'   combined_orginal_modified_column_wise
fi
done

for i in `cat /var/tmp/modified file`
do
if [[ -f $i ]]
then
for j in {1..10}
do
elif [[ -f $i$j ]]
then
echo "$i$j exsists"
fi
done
else
awk -v i="$i" -v j="$j" '{print "mv" " " $1 " " ij}'  combined_orginal_modified_column_wise
fi


done

관련 정보