他の 回答では、この質問の2つの主要な側面の1つに対処しています。それは、必要な名前変更操作を正常に実行する方法です。この回答の目的は、rename
コマンドのコンテキストでの奇妙な「裸語は許可されていません」エラーメッセージの意味を含め、コマンドが機能しなかった理由を説明することです。
この回答の最初のセクションはrename
、Perlとの関係rename
と、コード引数である最初のコマンドライン引数をどのように使用するかについてです。2番目のセクションは、シェルが引数リストを構築するために拡張(具体的にはグロビング)を実行する方法についてです。3番目のセクションは、「Bareword not allowed」エラーを発生させるPerlコードで何が起こっているかについてです。最後に、4番目のセクションは、コマンドを入力してからエラーが発生するまでの間に行われるすべてのステップの要約です。
1. rename
が奇妙なエラーメッセージを表示したら、検索に「Perl」を追加します。
DebianとUbuntuでは、rename
コマンドはファイル名の変更を実行するPerlスクリプトです。このリリースの時点でまだサポートされている14.04 LTSを含む古いリリースでは、これはコマンドを指す(間接的に)シンボリックリンクでした。新しいリリースでは、代わりに新しいコマンドを指します。これら2つのPerlのrenameコマンドはほとんど同じように機能します。この回答の残りの部分については、両方を参照するだけにします。prename
file-rename
rename
このrename
コマンドを使用すると、誰かが書いたPerlコードを実行しているだけではありません。また、独自のPerlコードを記述してrename
、それを実行するように指示しています。これは、のようなオプション引数以外の、コマンドに渡す最初のコマンドライン引数が実際のPerlコードで構成されるためですrename
-n
。rename
コマンドは、それぞれの上で動作させるために、このコードを使用してパス名を使用すると、それに続くコマンドライン引数として渡していること。(パス名引数を渡さない場合は、代わりに1行に1つずつ、標準入力rename
からパス名を読み取ります。)
コードはループ内で実行され、ループはパス名ごとに1回繰り返されます。ループの各反復の先頭で、コードが実行される前に、現在処理されているパス名が特殊$_
変数に割り当てられます。コードによっての値が別の値に$_
変更される場合、そのファイルは新しい名前を持つように名前が変更されます。
Perlの多くの式は$_
、オペランドとして使用する他の式が指定されていない場合、変数に対して暗黙的に動作します。たとえば、置換式$str =~ s/foo/bar/
は、変数がfoo
保持する文字列内で最初に出現するをに変更するか、が含まれていない場合はそのままにします。あなただけ書いた場合、明示的に使用せずに作業を、それは上で動作します。これは、の略です。$str
bar
foo
s/foo/bar/
=~
$_
s/foo/bar/
$_ =~ s/foo/bar/
それは合格するのが一般的だ表現をするコードの引数(すなわち、最初のコマンドライン引数)として、しかし、あなたがする必要はありません。ループ内で実行する任意のPerlコードを指定して、の各値を調べ、(条件付きで)変更できます。s///
rename
$_
これには多くのクールで有用な結果がありますが、それらの大多数はこの質問と回答の範囲をはるかに超えています。これをここで取り上げる主な理由-実際、私がこの回答を投稿することにした主な理由-の最初の引数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
。Ubuntuでは、変更していない限り、インタラクティブシェルはBashです。そのため、上記のBashリファレンスマニュアルにリンクしました。
グロブパターンが単一の展開されていないコマンドライン引数としてに渡される可能性がある状況が1つありrename
ます。それがどのファイルとも一致しない場合です。この状況では、シェルが異なるとデフォルトの動作も異なりますが、Bashのデフォルトの動作は、単にglobをそのまま渡すことです。ただし、これが必要になることはめったにありません。必要な場合は、引用してパターンが拡張されないようにする必要があります。これは、だけでなく、任意のコマンドに引数を渡す場合にも当てはまります。rename
引用符は、グロビング(ファイル名の展開)だけではありません。引用符で囲まれていないテキストに対して、また引用符で囲まれたテキストに対してもシェルによって実行される他の展開があるためです。一般に、スペースを含むシェルによって特別に処理される可能性のある文字を含む引数を渡したいときはいつでも、できればquotesでそれを引用する必要があります。"
"
'
'
Perlコードにs/foo/bar/
は、シェルによって特別に扱われるものは含まれていませんが、私もそれを引用して-と記述しておいたほうがよいでしょう's/foo/bar/'
。(私はまだ引用について話していなかったとして実際には、唯一の理由は、私は、それが一部の読者に混乱するだろうとしていなかった。)それはPerlのコードがあることは非常に一般的ですので、私はこれは良いされているだろうと言う理由があるん含まれていますそのような文字、そしてそのコードを変更する場合、引用が必要かどうかを確認するのを忘れたかもしれません。対照的に、シェルでグロブを展開する場合は、引用符で囲まないでください。
3. Perlインタープリターが「裸語は許可されない」とはどういう意味か
質問で示したエラーメッセージはrename *.DAT *.dat
、を実行すると、シェル*.DAT
が1つ以上のファイル名のリストに展開され、それらのファイル名の最初がであったことを示していますb1.DAT
。後続のすべての引数(他の展開元*.DAT
と展開*.dat
元の両方)は、その引数の後にあるため、パス名として解釈されます。
実際に実行されたものはのようなものrename b1.DAT ...
でありrename
、最初の非オプション引数をPerlコードとして扱うため、問題は次のようになりb1.DAT
ます。
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で引用する主な目的は文字列を保護することではなく、文字列を記述することです。これは実際、ほとんどのプログラミング言語が自然言語に似ている方法です。英語では、犬がいるとすると、「あなたの犬」は2語のフレーズですが、あなたの犬は犬です。同様に、Perlでは'$foo'
は文字列$foo
ですが、名前は$foo
です。
ただし、他のほぼすべての汎用プログラミング言語とは異なり、Perlは引用符で囲まれていないテキストを文字列を言及しているものと解釈することもあります。同じ注文。それが裸語である場合(または他のシギル、以下を参照)、コードを解釈する他の意味を見つけることができなかった場合にのみ、コードをそのように解釈しようとします。次に、制限を有効にすることで指示しない限り、文字列として受け取ります。$
Perlの変数は、通常、変数の幅広いタイプを指定する、sigilと呼ばれる句読文字で始まります。たとえば、$
はスカラーを@
意味し、配列は%
意味し、ハッシュは意味します。(他のものがあります。)Doがない心配あなたが混乱(または退屈な)ことを発見した場合、私は唯一と言って、それを育てていますので、ときに有効な名前は Perlプログラムに表示されますがされていない印章が先行し、その名前裸語と言われる。
ベアワードはさまざまな目的に役立ちますが、通常、プログラム(またはプログラムで使用されるモジュール)で定義されている組み込み関数またはユーザー定義のサブルーチンを示します。Perlは何と呼ばれる機能を内蔵していないb1
かDAT
、Perlインタプリタがコードを見ているときに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
制限と他の2つが可能になります。use strict;
一般的に推奨される方法です。したがって、rename
コマンドはコードに対してこれを行います。そのため、そのエラーメッセージが表示されます。
4.要約すると、これが起こったことです。
- シェルが
b1.DAT
最初のコマンドライン引数として渡されました。これrename
は、各パス名引数のループで実行されるPerlコードとして扱われました。
- これは、オペレーターを意味し
b1
、DAT
接続されていると解釈されました.
。
b1
また、DAT
接頭辞が付いていないため、それらは裸語として扱われました。
- これらの2つの裸語は、組み込み関数またはユーザー定義のサブルーチンの名前と見なされていましたが、そのような名前はありませんでした。
- 「厳密なサブ」が有効になっていない場合、それらは文字列式
'b1'
と同様に扱われ、'DAT
'連結されます。これは、この機能が役に立たないことが多いことを示す、意図したものとはかけ離れています。
- しかし、「厳格な潜水艦は」理由は、有効になっていた
rename
すべての可能な制限を(vars
、refs
、およびsubs
)。したがって、代わりにエラーが発生しました。
rename
このエラーのために終了しました。この種のエラーは早期に発生したため、パスしなかった場合でも、ファイル名の変更は行われませんでした-n
。これは、ユーザーを意図しないファイル名の変更から保護し、場合によっては実際のデータ損失から保護することもできます。
Zannaに感謝します。Zannaは、この回答のより簡潔なドラフトでいくつかの重要な欠点に対処するのを助けてくれました。彼女がいなければ、この答えはあまり意味がなく、投稿されないかもしれません。