Подтвердить что ты не робот

Git переименовать много файлов и папок

Я пытаюсь переименовать много файлов в моем приложении и должен иметь возможность выполнять переименование во всех подкаталогах из корня приложения через git (т.е. git mv% filenamematch%% replacement%), который заменяет только соответствующий текст. Я не умею работать с bash скриптами.

update: было бы хорошо, если бы они также переименовали каталоги, которые также совпадают!

4b9b3361

Ответ 1

Это должно сделать трюк:

for file in $(git ls-files | grep %filenamematch% | sed -e 's/\(%filenamematch%[^/]*\).*/\1/' | uniq); git mv $file $(echo $file | sed -e 's/%filenamematch%/%replacement%/')

Чтобы следить за тем, что это делает, вам нужно понять, что трубопровод с "|" и подстановку команд с помощью "$ (...)". Эти мощные конструкции оболочки позволяют нам комбинировать несколько команд, чтобы получить нужный нам результат. См. Pipelines и Замена команд.

Вот что происходит в этом однострочном слое:

  • git ls-files: создает список файлов в репозитории Git. Это похоже на то, что вы можете получить из ls, за исключением того, что он выводит только файлы проекта Git. Исход из этого списка гарантирует, что ничего в вашем каталоге .git/не коснется.

  • | grep %filenamematch%: Мы берем список из git ls-files и обрабатываем его через grep, чтобы отфильтровать его только на имена файлов, содержащие искомое слово или шаблон.

  • | sed -e 's/\(%filenamematch%[^/]*\).*/\1/': Мы прокладываем эти соответствия через sed (редактор потока), выполняем (-e) sed s (substitute), чтобы вырезать любые/и последующие символы после нашего соответствующего каталога (если это будет один).

  • | uniq: В тех случаях, когда совпадение является каталогом, теперь, когда мы отрубили каталоги и файлы, может быть много совпадающих строк. Мы используем uniq, чтобы сделать их всех в одну строку.

  • for file in ...: Оболочка "для" команды будет перебирать все элементы (имена файлов) в списке. Каждое имя файла, в свою очередь, присваивает переменной "$ file", а затем выполняет команду после точки с запятой (;).

  • sed -e 's/%filenamematch%/%replacement%/': Мы используем echo, чтобы передать каждое имя файла через sed, снова используя команду substitute - на этот раз для выполнения нашей замены шаблона в имени файла.

  • git mv: Мы используем эту команду Git для mv существующего файла ($ file) для нового имени файла (тот, который был изменен sed).

Одним из способов понять это лучше было бы наблюдать каждый из этих шагов изолированно. Для этого запустите команды ниже в своей оболочке и посмотрите результат. Все они являются неразрушающими, только производя списки для вашего наблюдения:

  • git ls-files

  • git ls-files | grep %filenamematch%

  • git ls-files | grep %filenamematch% | sed -e 's/\(%filenamematch%[^/]*\).*/\1/'

  • git ls-files | grep %filenamematch% | sed -e 's/\(%filenamematch%[^/]*\).*/\1/' | uniq

  • for file in $(git ls-files | grep %filenamematch% | sed -e 's/\(%filenamematch%[^/]*\).*/\1/' | uniq); echo $file

  • for file in $(git ls-files | grep %filenamematch% | sed -e 's/\(%filenamematch%[^/]*\).*/\1/' | uniq); echo $file | sed -e 's/%filenamematch%/%replacement%/'

Ответ 2

Переименуйте файлы с помощью регулярного выражения с помощью команды rename:

rename 's/old/new/' *

Затем зарегистрируйте изменения с помощью Git, добавив новые файлы и удалив старые:

git add .
git ls-files -z --deleted | xargs -0 git rm

В новых версиях Git вместо этого можно использовать флаг --all:

git add --all .

Ответ 3

Поздно к участнику, но это должно работать в BASH (для файлов и каталогов, но я буду осторожен относительно каталогов):

find . -name '*foo*' -exec bash -c 'file={}; git mv $file ${file/foo/bar}' \;

Ответ 4

git mv внутри оболочки оболочки?

Какова цель git-mv?

(Предполагая, что вы находитесь на платформе с разумной оболочкой!)

Опираясь на ответ @Джонатан-Камениш:

# things between backticks are 'subshell' commands.  I like the $() spelling over ''
# git ls-files     -> lists the files tracked by git, one per line
# | grep somestring -> pipes (i.e., "|") that list through a filter
#     '|' connects the output of one command to the input of the next
# leading to:  for file in some_filtered_list
# git mv  f1 f2  ->  renames the file, and informs git of the move.
# here 'f2' is constructed as the result of a subshell command
#     based on the sed command you listed earlier.

for file in 'git ls-files | grep filenamematch'; do git mv $file 'echo $file | sed -e 's/%filenamematch%/%replacement%/''; done

Вот более длинный пример (в bash или аналогичный)

mkdir blah; cd blah; 
touch old_{f1,f2,f3,f4} same_{f1,f2,f3}
git init && git add old_* same_* && git commit -m "first commit"
for file in $(git ls-files | grep old); do git mv $file $(echo $file | sed -e 's/old/new/'); done
git status
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#   renamed:    old_f1 -> new_f1
#   renamed:    old_f2 -> new_f2
#   renamed:    old_f3 -> new_f3
#   renamed:    old_f4 -> new_f4
#

см. также: Специальный анализ данных из командной строки Unix

Ответ 5

Это хорошо сработало для моего варианта использования:

ls folder*/*.css | while read line; do git mv -- $line ${line%.css}.scss; done;

Объяснение:

  • ls folder*/*.css - использует ls для получения списка всех каталогов с файлами CSS, которые соответствуют шаблону glob. (Каталоги, начинающиеся с folder и содержащие файлы с расширениями .css)
  • while read line - while read line чтение в результирующем выводе команды ls
  • do git mv -- $line ${line%.css}.css - Выполнить git mv для построчного вывода (переменная $line содержит каждую строку), сопоставляя начало каждого имени файла и исключая расширение .css ( с ${line% и добавлением нового расширения .scss (-- используется для предотвращения неоднозначности между именами файлов и флагами)

Код ниже может быть использован для "пробного запуска" (на самом деле git mv не будет выполняться):

ls variant*/*.css | while read line; do echo git mv $line to ${line%.css}.scss; done;

Ответ 6

Я решил это для себя, используя https://github.com/75lb/renamer - отлично работал:-) Явно не делаю git mv, но git, похоже, все равно имеет дело с результатами.

Когда я выполнил все шаги в верхнем ответе, я застрял на последнем шаге, когда моя консоль ответила

for pipe quote>

Если кто-нибудь сможет это объяснить, я буду признателен!

Ответ 7

Обычно я использую NetBeans для создания такого типа вещей, потому что я избегаю командной строки, когда есть более простой способ. NetBeans поддерживает некоторую поддержку git, и вы можете использовать его в произвольном каталоге/файле через вкладку "Избранное".