파일 이름을 바꾸는 Bash 스크립트(배열의 이름 제외)

파일 이름을 바꾸는 Bash 스크립트(배열의 이름 제외)

현재 공백과 특정 이름을 제거하여 파일 이름을 바꾸는 스크립트가 있습니다. 지금까지 약 200개의 이름이 있으므로 제외할 이름의 배열이 더 나은 선택이 될 것이라고 생각했습니다.

prename -v 's/ /_/g' *

prename -v 's/_-_/_/g' *

prename -v 's/_\(Summer-HD\)//ig' *

prename -v 's/_\(Hammer\)//ig' *

prename -v 's/_\(Hardware-Hybrid\)//g' *

prename -v 's/_\(digital\)//ig' *

prename -v 's/_\(Resolution-SD\)//ig' *

지금까지 시도한 것은 제외하려는 이름을 반복하는 for 루프이지만 작동하지 않았습니다.

exclude=('(Summer-HD)' '(Hammer)' '(digital)' '(Resolution-SD)' '(Vacation)' '(Hammer-Hybrid)')

for x in "${exclude[@]}";
    do prename -v 's/$x/_/g' * {} \;
done

이 for 루프는 전혀 작동하지 않고 깜박이는 커서만 남습니다. prename에 변수를 전달할 수 있는지 잘 모르겠습니다. 큰따옴표 사용에 대한 몇 가지 제안을 기반으로 for 루프를 일부 수정했습니다.

for x in "${exclude[@]}";
    do prename -v 's/$x/_/g' *"$x"* {} \;
done

이것도 작동하지 않으며 이제 여기서 무슨 일이 일어나고 있는지 전혀 모릅니다. 현재 삭제하고 싶은 이름이 200개가 넘으므로 여전히 이름 배열을 원합니다. 이름에 관해서는 저는 그 생각에 동의하지 않습니다. sed 또는 awk가 도움이 될 수 있다고 들었습니다. 나는 그렇게 하고 싶지도 않습니다. 제공할 수 있는 아이디어나 도움에 감사드립니다.

답변1

스크립트 내에서 배열(또는 목록으로 구성된 정규식을 포함하는 스칼라 변수)을 정의할 수 있습니다 prename. 사전 이름 스크립트 내에서 유효한 Perl 코드를 사용할 수 있다는 점을 기억하세요.특수 Perl 스크립트). 예를 들어

$ touch foo_\(Summer-HD\)_\(digital\).mkv
$ prename -n 'BEGIN {
                our $exclude=join("|", qw(Summer-HD Hammer digital Resolution-SD Vacation Hammer-Hybrid));
              };

              our $exclude;
              s/_\((?:$exclude)\)//ig;' *
rename(foo_(Summer-HD)_(digital).mkv, foo.mkv)

여기에 주목할 만한 몇 가지 사항이 있습니다.

  1. 변수 범위 지정은 이름 바꾸기 스크립트에서 매우 중요하며 use strictpragma가 적용됩니다. 시청하세요 perldoc strict(더 많은 내용이 있지만,간단히 말해서:strict현재 범위에서 이전에 선언되지 않은 변수는 사용할 수 없습니다 .
  2. 변수 는 파일 이름당 한 번이 아니라 스크립트가 실행될 때 한 번만 실행되도록 $exclude블록에 정의됩니다 . BEGIN {}여기에는 문자로 연결된 배열 |, 즉 정규식 대체가 포함됩니다.
  3. ourBEGIN 블록 외부에서 공유할 수 있도록 변수 로 정의됩니다 . 즉, File::Rename패키지 범위 전체에서 사용할 수 있습니다. 이는 아마도 여러분이 알고 싶어하는 것 이상이므로 이름 바꾸기 스크립트의 전역 변수로 생각하면 됩니다. 메인 코드 블록도 이를 선언해야 합니다(만 사용됨 our $exclude;). 바라보다perldoc -f our
  4. qw()공백으로 구분된 단어 목록을 배열로 변환하는 Perl의 참조 연산자 중 하나입니다. 바라보다 perldoc -f qw. 그런데, Perl에서 "배열"과 "목록"은 거의 동의어입니다.perldoc -q difference.*list.*array

rename여러 번 실행하기보다는 한 번 실행하려면 더 긴 스크립트(또는 여러 옵션)를 사용해야 한다는 점도 주목할 가치가 있습니다 -e '...script...'. 예를 들어

$ prename -n 'BEGIN {
                our $exclude=join("|", qw(Summer-HD Hammer digital Resolution-SD Vacation Hammer-Hybrid));
              };

              our $exclude;

              s/ /_/g;
              s/_-_/_/g;
              s/_\((?:$exclude)\)//ig;' *

답변2

다음을 사용하는 것이 더 쉽습니다 zsh.

exclude=(
  '(Summer-HD)'
  '(Hammer)'
  '(digital)'
  '(Resolution-SD)'
  '(Vacation)'
  '(Hammer-Hybrid)'
)

pattern="_(${(j[|])${(b@)exclude}})"

autoload -Uz zmv
zmv '*' '${f//$~pattern}'

이는 ${(b)exclude}요소의 전역 연산자를 이스케이프 $exclude하고 ${(j[|])...}결과를 그것과 조인 하므로 결국 being (구체적으로: ) |으로 끝나고 일괄 renamer 내부에서 ksh93의 연산자를 사용하여 일치 항목을 null로 바꿉니다 .$pattern_(exclude1|exclude2...)_(\(Summer-HD\)|\(Hammer\)|\(digital\)|\(Resolution-SD\)|\(Vacation\)|\(Hammer-Hybrid\))${f//pattern[/replacement]}zmv

관련 정보