現在のパスの代わりにフルパスを使用すると、`rename` の動作が異なるのはなぜですか?

現在のパスの代わりにフルパスを使用すると、`rename` の動作が異なるのはなぜですか?

はい、私は質問に答えるOP は Ubuntu に複数のリポジトリを持っており、無関係なソフトウェアのインストールで問題が発生する可能性がある。1 行で PPA を無効にしてから、一連の手順に従うことをお勧めします。すべて問題ないので、この質問は回答済みのままにしておきます... いいえ。期待どおりに動作しなかったrename結果:rename

sudo rename s/list/list\.disable/g /etc/apt/sources.list.d/*.list

/etc/apt/sources.list.d/これで、 rename がで終わるファイルを調べてを に.list置き換えることを期待しています。ほぼ同じコマンドで別の回答がありましたが、OP はフィードバックをくれませんでした。私は最初にテストせずに理論を投げかけています。そのため、OP が次の行に問題を見つけたのは驚きです。.list.list.disable

Can't rename /etc/apt/sources.list.d/iaz-battery-status-quantal.list /etc/apt/sources.list.disable.d/iaz-battery-status-quantal.list.disable: No such file or directory
Can't rename /etc/apt/sources.list.d/ubuntu-wine-ppa-quantal.list /etc/apt/sources.list.disable.d/ubuntu-wine-ppa-quantal.list.disable: No such file or directory
Can't rename /etc/apt/sources.list.d/webupd8team-java-raring.list /etc/apt/sources.list.disable.d/webupd8team-java-raring.list.disable: No such file or directory

奇妙な感じがしたので、自分でその理論をテストしてみると、同じ結果が出ました。そして、問題が発生するたびに、通常は正規表現ではなく? 正規表現をさまざまな方法で変更しました:

  • s/.list/.list.disable/g
  • s/.list/.list.disable/g
  • /リスト/リスト.無効/
  • 覚えていない他の組み合わせ

まあ、正規表現は問題ではないと判断したので、セレクターに目を向けて、それを変更して/etc/apt/sources.list.d/*正規表現テストをリサイクルしました。うまくいきませんでした。少しイライラしてtouch some.list、コマンドを適用しました。

rename s/\.list/\.list\.disable/g *

ビンゴ!今、私はすっかり騙された気分です。私は答えを修正して、自分の人生を続けます... いや!これは受け入れられません。なぜ?私はマニュアルを調べましたが、驚いたことに、現在のパスの例だけが使われていました。これは正常ですか?それとも、関数が実装されていないだけですか?それとも、私の理論を疑うべきでしょうか?

答え1

パターンをテストするときに非常に役立つドライラン モードで-n実行するには、次のパラメータを使用します。rename

martin@martin ~ % rename -n s/list/list.disable/g /etc/apt/sources.list.d/*.list | sed 's/renamed as/\n =>/g'
[...]
/etc/apt/sources.list.d/spotify.list 
 => /etc/apt/sources.list.disable.d/spotify.list.disable
/etc/apt/sources.list.d/steam.list 
 => /etc/apt/sources.list.disable.d/steam.list.disable
[...]

ここでの明らかなエラーは、パターンがlistに一致するため、フォルダーとそこに含まれるファイルの両方の名前を変更しようとしていることです。sources.list.d

代わりに次のパターンを使用します:

rename -n 's/\.list$/.list.disable/' /etc/apt/sources.list.d/*.list | sed 's/renamed as/\n =>/g'
[...]
/etc/apt/sources.list.d/spotify.list 
 => /etc/apt/sources.list.d/spotify.list.disable
/etc/apt/sources.list.d/steam.list 
 => /etc/apt/sources.list.d/steam.list.disable
[...]

違いは次のとおりです。

  1. .検索パターンで を として引用すると\.、ドットが実際のドットにのみ一致し、任意の文字に一致しないことが保証されます (正規表現で引用符で囲まれていないドットは通常、これに該当します)。

  2. after list$は「文字列の終わり」を意味します。これにより、パスまたはファイル名の別の場所にある「.list」ではなく、ファイル名の末尾にある「.list」のみが一致して置換されることが保証されます。

  3. 置換文字列内のドットを引用符で囲む必要はありません。ドットは.もはや特別な意味を持たないため、「.list.disable」はバックスラッシュなしでも機能します。

  4. また、シェルが正規表現を変更しないようにするために、正規表現を一重引用符で囲んでいることにも注意してください。

答え2

g問題は、パターンをアンカーするべきときにグローバル スイッチを使用していることです。次のように記述します。

s/a/b/g

文字列内のすべての a を b に置き換えます。これにより、ディレクトリが存在しないパスに名前を変更しようとします。また、ディレクトリ内で操作を実行して置換する一致が 1 つだけになったときに、問題が解消されたのもこのためです。

パターンを固定することを意図していたのではないかと思います

s/\.list$/.list.disable/

これにより、存在しないディレクトリ /etc/apt/sources.list.disable.d/ にファイルを移動しようとする試みが防止されます (したがって、そこにファイルを移動することはできません)。

関連情報