git重命名许多文件和文件夹

git rename many files and folders

我正在尝试重命名我的应用程序中的许多文件,并且需要能够在应用程序根目录下通过git(即git mv%filenamematch %% replacement%)在所有子目录中进行重命名,只替换匹配的文本。 我对bash脚本没有好处。

更新:如果还重命名匹配的目录也会很好!


这应该做的伎俩:

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%/')

要了解这是做什么的,你需要用"|"来理解管道并用"$(...)"替换命令。这些强大的shell结构允许我们组合几个命令来获得我们需要的结果。请参阅管道和命令替换。

以下是这个单行中发生的事情:

  • git ls-files:这会在Git存储库中生成一个文件列表。它类似于你从ls得到的,除了它只输出Git项目文件。从此列表开始确保您的.git /目录中没有任何内容被触及。

  • | grep %filenamematch%:我们从git ls-files获取列表并通过grep将其过滤以将其过滤为仅包含我们正在寻找的单词或模式的文件名。

  • | sed -e 's/\(%filenamematch%[^/]*\).*/\1/':我们通过sed(流编辑器)管理这些匹配,执行(-e)sed的s(替换)命令来切断匹配目录后的任何/后续字符(如果它恰好是一个)。

  • | uniq:如果匹配是一个目录,现在我们已经切断了包含的目录和文件,可能会有很多匹配的行。我们使用uniq将它们全部组合成一行。

  • for file in ...:shell的"for"命令将遍历列表中的所有项目(文件名)。依次为每个文件名,它分配给变量"$ file",然后在分号(;)之后执行命令。

  • sed -e 's/%filenamematch%/%replacement%/':我们使用echo通过sed管道每个文件名,再次使用它的替换命令 - 这次在文件名上执行模式替换。

  • git mv:我们使用这个git命令将现有文件($ file)转换为新文件名(由sed更改的文件名)。

  • 更好地理解这一点的一种方法是单独观察这些步骤。为此,请在shell中运行以下命令,并观察输出。所有这些都是非破坏性的,只为您的观察产生列表:

  • 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%/'


  • 使用命令rename使用正则表达式重命名文件:

    1
    rename 's/old/new/' *

    然后通过添加新文件并删除旧文件,使用Git注册更改:

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

    在较新版本的Git中,您可以使用--all标志:

    1
    git add --all .


    迟到了,但是,这应该在BASH中工作(对于文件和目录,但我对目录要小心):

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


    shell循环中的git mv

    git-mv的目的是什么?

    (假设你在一个有合理外壳的平台上!)

    在@ jonathan-camenish的答案基础上:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    # 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或类似的)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    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命令行中的Ad Hoc数据分析


    这适用于我的用例:

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

    说明:

    • ls folder*/*.css - 使用ls获取具有与glob模式匹配的CSS文件的所有目录的列表。 (以folder开头并包含.css扩展名的文件的目录)
    • while read line - 逐行读取ls命令的结果输出
    • do git mv -- $line ${line%.css}.css - 在逐行输出($line变量包含每一行)上执行git mv,同时匹配每个文件名的开头并排除.css扩展名(使用${line%并添加新的 extension(--用于防止文件名和标志之间的歧义)

    下面的代码可用于"干运行"(实际上不会执行git mv):

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

    我用自己解决了这个问题
    https://github.com/75lb/renamer - 完美地工作:-)
    没有明确地做git mv但git似乎完全处理结果。

    当我按照最高答案中的所有步骤操作时,我在最后一步卡住了,当我的控制台响应时

    for pipe quote>

    如果有人能解释这一点,我会很感激!


    我通常使用NetBeans来执行此类操作,因为当有更简单的方法时我会避开命令行。 NetBeans对git有一些支持,您可以通过"收藏夹"选项卡在任意目录/文件中使用它。