Почему `rename` ведет себя по-разному, когда я использую полный путь вместо текущего?

Почему `rename` ведет себя по-разному, когда я использую полный путь вместо текущего?

Хорошо, яотвечая на вопросгде у OP есть несколько репозиториев в Ubuntu, которые могут вызывать проблемы с установкой несоответствующего программного обеспечения. Я рекомендую отключить PPA с помощью одной строки, renameа затем следовать серии инструкций. Все хорошо, и я просто оставляю этот вопрос как отвеченный... нет. Результаты, которые renameне вели себя так, как я ожидал:

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

При этом я ожидаю, что rename проверит /etc/apt/sources.list.d/любой файл, заканчивающийся на , .listи заменит его .listна .list.disable. У меня был другой ответ с почти такой же командой, но OP так и не дал обратной связи, и я как бы бросаю теорию без предварительного тестирования. Поэтому я удивлен, что OP нашел проблемы со строкой:

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
  • /list/list.disable/
  • другие комбинации, которые я не помню

Ну, я решил, что проблема не в регулярном выражении, поэтому я смотрю на селектор, меняю его на /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. Список $после означает "конец строки". Он гарантирует, что только ".list" в конце имени файла совпадает и будет заменен, а не ".list", который находится где-то еще в пути или имени файла.

  3. Вам не нужно заключать точку в кавычки в строке замены; поэтому «.list.disable» работает без обратных косых черт, поскольку .больше не имеет там особого значения.

  4. Также обратите внимание, что я заключил регулярное выражение в одинарные кавычки, чтобы оболочка не могла каким-либо образом его изменить.

решение2

Проблема в использовании глобального переключателя, gкогда на самом деле вместо этого нужно было закрепить шаблон. Как вы написали:

s/a/b/g

заменяет все a на b везде в строке. Это заставляет вас пытаться переименовывать пути, для которых не существует каталога. Это также причина, по которой проблема исчезала, когда вы выполняли операцию внутри каталога, так что для замены оставалось только одно совпадение.

Я думаю, вы, возможно, намеревались закрепить шаблон

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

что предотвратило бы попытку переместить файл в каталог /etc/apt/sources.list.disable.d/, который не существует (поэтому вы не можете переместить в него файл).

Связанный контент