다른 답변 은이 질문의 두 가지 주요 측면 중 하나를 설명했습니다. 필요한 이름 바꾸기 작업을 성공적으로 수행하는 방법입니다. 이 답변의 목적은 명령 컨텍스트에서 이상한 "허용되지 않은"오류 메시지의 의미를 포함하여 명령이 작동하지 않은 이유를 설명하는 것 rename
입니다.
이 답변의 첫 번째 섹션은 rename
Perl과 의 관계 및 rename
전달하는 첫 번째 명령 행 인수 (코드 인수)를 사용하는 방법에 관한 것입니다. 두 번째 섹션은 쉘이 인수 목록을 구성하기 위해 확장 (특히 globbing)을 수행하는 방법에 관한 것입니다. 세 번째 섹션은 "Bareword not allowed"오류를 발생시키는 Perl 코드에서 수행되는 작업에 관한 것입니다. 마지막으로, 네 번째 섹션은 명령 입력과 오류 발생 사이에 발생하는 모든 단계를 요약 한 것입니다.
1. rename
이상한 오류 메시지가 나타나면 "Perl"을 검색에 추가하십시오.
데비안과 우분투에서이 rename
명령은 파일 이름 바꾸기를 수행 하는 Perl 스크립트입니다. 이 글을 쓰는 시점에서 여전히 지원되는 14.04 LTS를 포함한 이전 릴리스 에서는 명령 을 가리키는 ( 직접적으로 ) 심볼릭 링크 였습니다 . 최신 릴리스에서는 최신 명령 을 가리 킵니다 . 이 두 Perl 이름 바꾸기 명령 은 대부분 같은 방식으로 작동하며이 답변의 나머지 부분에 대해 두 가지를 모두 언급하겠습니다 .prename
file-rename
rename
이 rename
명령 을 사용하면 다른 사람이 작성한 Perl 코드 만 실행하는 것이 아닙니다. 또한 자신의 Perl 코드를 작성 rename
하고 실행하도록 지시하고 있습니다. 때문이다 첫 번째 명령 줄 인수 당신이에 전달 rename
이외의 명령, 옵션 인수 등은 -n
, 실제 펄 코드로 구성된다 . 이 rename
명령은이 코드를 사용 하여 이후의 명령 줄 인수로 전달한 각 경로 이름 에서 작동합니다 . (경로 이름 인수를 전달하지 않으면 표준 입력 에서 한 줄에 하나씩 rename
경로 이름 을 읽습니다 .)
코드는 loop 내부 에서 실행 되며 경로 이름마다 한 번씩 반복 됩니다. 루프가 반복 될 때마다 코드가 실행되기 전에 특수 $_
변수 에 현재 처리중인 경로 이름이 할당됩니다. 코드로 인해 값이 $_
다른 것으로 변경되면 해당 파일의 이름이 새 이름으로 바뀝니다.
Perl의 많은 표현식$_
은 피연산자 로 사용할 다른 표현식이없는 경우 변수 에 대해 내재적으로 작동합니다 . 예를 들어, 대체 표현식 은 변수 가 보유한 문자열에서 $str =~ s/foo/bar/
첫 번째 항목을 foo
로 변경하거나을 포함하지 않으면 변경되지 않은 상태로 둡니다 . 방금 작성하는 경우 명시 적으로 사용하지 않고 연산자를 , 그것은에 운영 . 이것은 짧다 .$str
bar
foo
s/foo/bar/
=~
$_
s/foo/bar/
$_ =~ s/foo/bar/
표현식 을 코드 인수 (즉, 첫 번째 명령 행 인수) 로 전달 하는s///
것이 일반적 rename
이지만 반드시 그럴 필요는 없습니다. 루프 내에서 실행될 Perl 코드를 제공하여 각 값을 검사 $_
하고 조건부로 수정할 수 있습니다.
이것은 시원하고 유용한 결과 가 많이 있지만, 대부분은이 질문과 답변의 범위를 벗어납니다. 내가 이것을 여기에 가져온 주된 이유-사실이 대답을 게시하기로 결정한 주된 이유는-첫 번째 인수 rename
가 실제로 Perl 코드 이기 때문에 이상한 오류 메시지가 표시되고 검색을 통해 정보를 찾는 데 어려움이있는 경우 검색 문자열에 "Perl"을 추가하거나 "rename"을 "Perl"로 바꾸는 경우가 종종 있습니다.
2.와 rename *.DAT *.dat
의 rename
명령은 본 적이 *.DAT
!
같은 명령은 rename s/foo/bar/ *.txt
일반적으로 통과하지 않는 *.txt
받는 명령 줄 인수로 rename
프로그램, 그리고 당신이 그것을하고 싶지 않아 , 당신은 이름이 그대로있는 파일이 없으면 *.txt
희망 당신은하지 않습니다.
rename
해석하지 않습니다 글로브 패턴이 좋아 *.txt
, *.DAT
, *.dat
, x*
, *y
, 또는 *
경로 이름 인수로 전달합니다. 대신, 쉘은 경로 확장 을 수행 합니다 (파일 이름 확장이라고도하며 글 로빙이라고도 함). 이것은 rename
유틸리티가 실행 되기 전에 발생 합니다. 쉘은 글롭을 잠재적으로 여러 경로 이름으로 확장하여 별도의 명령 행 인수로에 모두 전달합니다 rename
. 우분투에서 대화 형 쉘은 변경하지 않는 한 Bash 이므로 위 의 Bash 참조 매뉴얼에 링크했습니다 .
glob 패턴이 확장되지 않은 단일 명령 행 인수로 전달 될 수있는 상황이 하나 rename
있습니다. 파일과 일치하지 않는 경우입니다. 이 상황에서 다른 쉘은 다른 기본 동작을 나타내지 만 Bash의 기본 동작은 단순히 글로브를 단순히 통과시키는 것입니다. 그러나 당신은 이것을 거의 원하지 않습니다! 원하는 경우 패턴을 인용 하여 패턴이 확장되지 않았 는지 확인 해야 합니다. 이것은뿐만 아니라 모든 명령에 인수를 전달합니다 .rename
인용 부호는 글 로빙 (파일명 확장)을위한 것이 아닙니다. 쉘이 인용되지 않은 텍스트에 대해 수행하는 다른 확장 이 있고, 일부에 대해서는 인용 부호로 묶인 텍스트에 대해서도 확장 이 있기 때문 "
"
입니다. 일반적으로 공백을 포함하여 쉘에서 특수하게 처리 할 수있는 문자가 포함 된 인수를 전달하려면 항상 따옴표로 인용해야 '
'
합니다 .
Perl 코드 s/foo/bar/
에는 쉘에서 특별히 다루는 것이 포함되어 있지 않지만 인용하고 작성하는 것이 좋을 것입니다 's/foo/bar/'
. (사실, 내가 한 유일한 이유는 없습니다 아직 인용에 대해 이야기하지 않았다대로, 일부 독자들에게 혼동 될 것이 었습니다.) 그 이유는 내가 펄 코드는 매우 일반적이기 때문에이되었을 것이다 좋은 말할 않습니다 포함 이러한 문자를 사용하고 해당 코드를 변경하려는 경우 인용이 필요한지 확인하지 못할 수 있습니다. 반대로, 쉘이 glob를 확장하도록하려면 인용 되지 않아야 합니다.
3. Perl 인터프리터가 "허용되지 않음"이라는 의미
질문에 표시된 오류 메시지는을 실행할 때 rename *.DAT *.dat
쉘 *.DAT
이 하나 이상의 파일 이름 목록으로 확장 되었으며 해당 파일 이름 중 첫 번째 파일 이름이 임을 나타 b1.DAT
냅니다. 이후의 모든 인수는 다른 인수에서 *.DAT
확장 *.dat
되거나 확장 된 이후 모두 해당 인수 뒤에 오기 때문에 경로 이름으로 해석됩니다.
실제로 실행 된 것은와 같았고 옵션이 아닌 첫 번째 인수를 Perl 코드로 취급 rename b1.DAT ...
하기 때문에 rename
질문은 다음 b1.DAT
과 같이됩니다. Perl 코드로 실행할 때 "허용되지 않는"오류 가 발생하는 이유는 무엇입니까?
Bareword "b1" not allowed while "strict subs" in use at (user-supplied code).
Bareword "DAT" not allowed while "strict subs" in use at (user-supplied code).
쉘에서 우리는 다른 문자열로 자동 변환하는 의도하지 않은 쉘 확장 으로부터 문자열 을 보호하기 위해 문자열 을 인용 합니다 (위 섹션 참조). 쉘은 범용 언어와는 매우 다르게 작동하는 특수 목적의 프로그래밍 언어 이며 매우 이상한 구문과 의미가이를 반영합니다. 그러나 Perl은 범용 프로그래밍 언어 이며, 대부분의 범용 프로그래밍 언어 와 마찬가지로 Perl에서 인용하는 주된 목적은 문자열 을 보호하는 것이 아니라 전혀 언급하는 것입니다. 이것은 실제로 대부분의 프로그래밍 언어가 자연 언어 와 유사한 방식 입니다. 영어로, 개가 있다고 가정하면, "개"는 두 단어로 된 반면, 개는 개입니다. 마찬가지로 Perl에서 '$foo'
문자열 $foo
은 이름이지만 이름은 $foo
입니다.
그러나 거의 모든 다른 범용 프로그래밍 언어와는 달리, 펄 것 또한 때때로으로 인용되지 않은 텍스트를 해석 언급 이 동일한 문자로 구성되어 있다는 점에서, 그것과 "동일한"인 문자열을 - 문자열을 같은 순서. 코드가 간결한 경우 ( $
또는 다른 sigil이 없거나 아래 참조) 코드를 해석하려고 시도하고 다른 의미를 찾지 못하면 코드를 해석하려고 시도 합니다. 그런 다음 제한 을 활성화하여 알리지 않는 한 문자열로 사용합니다 .
Perl의 변수는 일반적으로 변수 의 넓은 유형을 지정 하는 sigil 이라는 문장 부호 문자로 시작 합니다. 예를 들어, $
수단 스칼라 , @
수단 배열 및 %
수단 해시 . ( 다른 사람이 있습니다. ) 당신이 혼란 (또는 지루한) 찾을 경우 어떻게하지 걱정, 난 단지 말을 꺼내는거야 때문 유효한 이름 펄 프로그램에서 나타나지만가되어 있지 시길 앞에, 그 이름 간결한 것으로 알려져 있습니다 .
Bareword는 다양한 용도로 사용되지만 일반적으로 프로그램 (또는 프로그램에서 사용하는 모듈)에 정의 된 내장 기능 또는 사용자 정의 서브 루틴 을 나타냅니다 . 펄은 더 호출되는 함수 내장 없다 b1
또는 DAT
펄 인터프리터 코드를 볼 때, b1.DAT
그것은 치료를 시도 b1
하고 DAT
서브 루틴의 이름으로. 이러한 서브 루틴이 정의되어 있지 않으면 실패합니다. 그런 다음 제한 사항 이 사용 가능하지 않으면이를 제한 조건 으로 문자열로 취급합니다. 실제로 이것이 의도 했는지 여부 는 누구나 추측 할 수 있지만 이것은 효과가 있습니다 . Perl의 .
연산자는 문자열을 연결 하므로 문자열 로 b1.DAT
평가됩니다.b1DAT
. 즉, 나 b1.DAT
같은 것을 쓰는 나쁜 방법 입니다.'b1' . 'DAT'
"b1" . "DAT"
perl -E 'say b1.DAT'
짧은 Perl 스크립트 say b1.DAT
를 Perl 인터프리터로 전달 하는 명령을 실행하여이를 직접 테스트하여 실행할 수 있습니다 b1DAT
. (이 명령에서 '
'
따옴표를 통과 쉘에게 say b1.DAT
하나의 명령 줄 인수로, 그렇지 않으면 공간을 야기 say
하고 b1.DAT
하는 별도의 단어로 분석 하고 perl
별도의 인수로받을 것입니다. perl
않습니다 하지 따옴표 자체를 참조로 쉘이 제거합니다 .)
그러나 이제use strict;
Perl 스크립트를 작성해보십시오say
. 이제는 같은 종류의 오류로 실패합니다 rename
.
$ perl -E 'use strict; say b1.DAT'
Bareword "b1" not allowed while "strict subs" in use at -e line 1.
Bareword "DAT" not allowed while "strict subs" in use at -e line 1.
Execution of -e aborted due to compilation errors.
이것은 use strict;
Perl 인터프리터가 베어 워드를 문자열로 취급하는 것을 금지 했기 때문에 발생했습니다 . 이 특정 기능을 금지하려면 subs
제한 을 설정하는 것만으로도 충분합니다 . 이 명령은 위와 동일한 오류를 생성합니다.
perl -E 'use strict "subs"; say b1.DAT'
그러나 일반적으로 Perl 프로그래머는 단지 쓰기 만 use strict;
할 subs
것입니다. use strict;
일반적으로 권장되는 방법입니다. 따라서 rename
명령은 코드에 대해이 작업을 수행 합니다 . 그렇기 때문에 오류 메시지가 나타납니다.
4. 요약하면 다음과 같습니다.
- 셸
b1.DAT
은 첫 번째 명령 줄 인수로 전달 되었으며, rename
각 경로 이름 인수에 대해 루프에서 실행되는 Perl 코드로 처리되었습니다.
- 이것은 운영자 를 의미
b1
하고 DAT
연결하는 것으로 .
간주되었습니다.
b1
및 DAT
sigils로 시작하지 않았다, 그래서 그들은 barewords으로 처리 하였다.
- 이 두 개의 베어 워드는 내장 함수 또는 사용자 정의 서브 루틴의 이름으로 사용되었지만 그러한 이름은 없었습니다.
- "strict subs"가 활성화되어 있지 않으면 문자열 표현식처럼 취급
'b1'
되고 'DAT
'연결됩니다. 의도 한 것과는 거리가 멀기 때문에이 기능이 종종 도움이되지 않는 방법을 보여줍니다.
- 때문에 그러나 "엄격한 잠수정은"활성화 된
rename
모든 수 제한 ( vars
, refs
, 및 subs
). 따라서 대신 오류가 발생했습니다.
rename
이 오류로 인해 종료하십시오. 이러한 종류의 오류는 일찍 발생했기 때문에 통과하지 않아도 파일 이름 바꾸기 시도가 수행되지 않았습니다 -n
. 이것은 의도하지 않은 파일 이름 변경과 때로는 실제 데이터 손실로부터 사용자를 보호하는 좋은 방법입니다.
Zanna 에게 감사의 말을 전한다 . 이 답변을보다 초안으로 작성하여 몇 가지 중요한 단점을 해결하도록 도와주었습니다 . 그녀가 없었다면이 대답은 의미가 떨어졌을 것이며 전혀 게시되지 않았을 것입니다.