Perl 스크립트를 사용하여 Linux에서 파일 이름 바꾸기

Perl 스크립트를 사용하여 Linux에서 파일 이름 바꾸기

Linux 시스템에 "pre_"와 같은 접두사가 붙은 파일 세트가 있는데 이를 삭제하여 모든 파일의 이름을 바꾸고 싶습니다. 이것은 내가 작성한 Perl 코드입니다. 오류는 발생하지 않지만 작업은 아직 완료되지 않았습니다.

#!/usr/bin/perl -w
my @files = `ls -1 | grep -i \"pre_.*\"`;
foreach $file ( @files )
{
  my @names = split(/pre_/, $file);
  my $var1 = $names[1];
  'mv "$file" "$var1"';
}

답변1

당신은 아무것도 실행하지 않습니다. 작은따옴표( ) 안에 무언가를 넣으면 ''이는 단지 문자열이므로 'mv "$file" "$var1"'명령이 아니며 문자열이며 아무 작업도 수행하지 않습니다. 문자열 자체는 참인 진술입니다. 이 명령을 실행하려면 다음을 사용해야 합니다.

system "mv", "--", $file, $var1;

(아니요 system("mv '$file' '$var1'")이로 인해 명령 주입 취약점이 발생합니다.)

하지만 꼭 그럴 필요는 없습니다 . 다음과 perl같은 기능을 rename()사용하면 됩니다.

rename($file, $var1)

다음으로, 실제로 구문 분석해서는 안되는 출력은 ls다음과 같습니다.매우 나쁜 생각이고 깨지기 쉽습니다.. 또한 Perl(또는 다른 프로그래밍 언어)에서는 전혀 필요하지 않습니다. 해당 문자열을 포함하는 현재 디렉터리의 모든 파일을 일치시키려면 pre_(이것이 바로 grep수행하는 작업입니다. 그럴 필요는 없지만 grep을 사용하면 됩니다 ls -d -- *pre_*) 다음을 사용할 수 있습니다 glob().

my @files = glob("*pre_*");

따라서 이 모든 것을 종합하면 다음과 같습니다.

#!/usr/bin/perl -w
use File::Glob qw(:globally :nocase);
my @files = glob("*pre_*");
foreach $file ( @files )
{
  my @names = split(/pre_/i, $file);
  rename($file, $names[1]);
}

그러나 그것은 정말로 좋은 생각이 아닙니다. 동일한 접두어(예: pre_file1apre_file1)를 가진 두 개의 파일이 있는 경우 첫 번째 파일은 두 번째 파일로 덮어쓰여집니다. 이 예에서는 file1명령이 pre_그 앞의 모든 항목을 삭제하므로 두 파일의 이름이 모두 변경됩니다. 따라서 경고를 추가하고 다음 파일을 건너뛸 수 있습니다.

#!/usr/bin/perl -w
use File::Glob qw(:globally :nocase);

my @files = glob("*pre_*");
foreach $file ( @files )
{
  my @names = split(/pre_/i, $file);
  if (-e $names[1]) {
    warn "Warning: Not renaming '$file' to '$names[1]' " .
        "because '$names[1]' exists.\n";
    next;
  }
  rename($file, $names[1]) or
    warn "rename '$file': $!\n";
}

물론 이것은 모두 바퀴를 재발명하는 것입니다. 직접 설치한 다음 perl-rename(Debian, Ubuntu 등에서 실행 , 다른 시스템에서는 또는 apt install rename이라고 함 ) 다음을 수행할 수 있습니다(대소문자를 구분하지 않지만 포함된 파일만 찾습니다 ).prenameperl-renamepre_

rename -n 's/.*?pre_//si' ./*

실제 이름을 바꾸지 않고 수행할 작업만 인쇄합니다 -n. rename이름 바꾸기가 예상대로 작동한다고 확신하면 -n실제로 파일 이름을 바꾸지 않고 명령을 다시 실행하십시오.

껍질이 여기를 통과합니다모두(숨겨지지 않은) 파일이며 코드에 의해 이름이 변경되지 않은 파일은 rename무시 됩니다. 또한 in , in 을 통해 대소문자를 구분하지 않는 파일 이름만 전달하도록 셸에 지시 하거나 전역 설정 옵션을 사용할 수도 있습니다.renameperlpre_./~(i)*pre_*ksh93./(#i)*pre_*zsh -o extendedglobnocaseglobbashzshyash./*[pP][rR][eE]_*

답변2

필요한 도구가 이미 존재합니다 rename(배포판에 따라 다름 perl-rename) prename.

rename 's/^pre_//' file1 file2 ...

-n시험 실행 및 목록 이름 변경 에 사용됩니다 -v.

rename참고: 다르게 작동하는 명령과 혼동하지 마십시오 util-linux.

답변3

...다른 이름 바꾸기 대안이 있습니다("바퀴를 재발명"하는 것보다) 예...

사용mmv이와 같이:

$ mmv -n '*_*.ext' '#2.ext'
pre_file_number1.ext -> file_number1.ext
pre_file_number2.ext -> file_number2.ext
pre_file_number3.ext -> file_number3.ext
pre_file_number4.ext -> file_number4.ext

또는 Z Shell(zsh) 내장 함수를 사용하여zmv이와 같이:

% autoload zmv
% zmv -n '*.ext' '${f#*_}' 
mv -- pre_file_number1.ext file_number1.ext
mv -- pre_file_number2.ext file_number2.ext
mv -- pre_file_number3.ext file_number3.ext
mv -- pre_file_number4.ext file_number4.ext

참고: -n위의 두 경우 모두 안전한 시험 실행입니다. 출력이 만족스러우면 제거하거나 -v(자세한 설명을 위해) 실제 이름 변경이 발생합니다.

관련 정보