web-dev-qa-db-ja.com

gitは多くのファイルとフォルダの名前を変更します

アプリケーション内の多くのファイルの名前を変更しようとしていますが、アプリのルートからgit(つまり、git mv%filenamematch %% replacement%)までのすべてのサブディレクトリで、一致するテキストのみを置き換える名前変更を実行できる必要があります。しかし、私はbashスクリプトが苦手です。

更新:同じように一致するディレクトリの名前も変更するとよいでしょう!

30
Jonathan

これでうまくいくはずです:

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

これが何をしているのかを追跡するには、「|」を使用した配管を理解する必要があります。 「$(...)」によるコマンド置換。これらの強力なシェル構造により、いくつかのコマンドを組み合わせて必要な結果を得ることができます。 パイプライン および コマンド置換 を参照してください。

このワンライナーで何が起こっているかは次のとおりです。

  1. _git ls-files_:これにより、Gitリポジトリ内のファイルのリストが生成されます。 lsから取得できるものと似ていますが、Gitプロジェクトファイルのみを出力する点が異なります。このリストから開始すると、.git /ディレクトリ内の何も変更されないことが保証されます。

  2. _| grep %filenamematch%_:_git ls-files_からリストを取得し、それをgrepにパイプして、探している単語またはパターンを含むファイル名のみにフィルターします。

  3. | sed -e 's/\(%filenamematch%[^/]*\).*/\1/':これらの一致を sed (ストリームエディター)にパイプし、(-e)sedのs(substitute)コマンドを実行して、一致するディレクトリの後の/以降の文字を切り落とします。 (たまたま1つである場合)。

  4. _| uniq_:一致がディレクトリである場合、含まれているディレクトリとファイルを切り取ったので、一致する行が多数ある可能性があります。 uniqを使用して、それらすべてを1行にします。

  5. _for file in ..._:シェルの "for"コマンド は、リスト内のすべてのアイテム(ファイル名)を反復処理します。各ファイル名は順番に変数「$ file」に割り当てられ、セミコロン(;)の後にコマンドを実行します。

  6. _sed -e 's/%filenamematch%/%replacement%/'_: echo を使用して、sedを介して各ファイル名をパイプ処理し、その代替コマンドを再度使用します。今回は、ファイル名のパターン置換を実行します。

  7. _git mv_:このgitコマンドを使用して、既存のファイル($ file)を新しいファイル名(sedによって変更されたファイル名)にmvします。

これをよりよく理解する1つの方法は、これらの各ステップを個別に観察することです。これを行うには、シェルで以下のコマンドを実行し、出力を確認します。これらはすべて非破壊的であり、観察用のリストのみを作成します。

  1. _git ls-files_

  2. _git ls-files | grep %filenamematch%_

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

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

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

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

29

コマンドrenameを使用して、正規表現でファイルの名前を変更します。

rename 's/old/new/' *

次に、新しいファイルを追加し、古いファイルを削除して、変更をGitに登録します。

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

Gitの新しいバージョンでは、代わりに--allフラグを使用できます。

git add --all .
14
Flimm

パーティーに遅れましたが、これはBASHで機能するはずです(ファイルとディレクトリの場合ですが、ディレクトリについては注意が必要です)。

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

git mvシェルループ内?

git-mvの目的は何ですか?

(妥当なシェルを備えたプラットフォーム上にいると仮定します!)

構築 @ jonathan-camenishによる回答

# 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
#

参照: nixコマンドラインからのアドホックデータ分析

5
Gregg Lind

https://github.com/75lb/renamer -完全に機能しました:-)明示的にgit mvを実行しませんが、gitは結果を処理しているようです。とにかく完全に。

トップアンサーのすべての手順を実行すると、コンソールが次のように応答したときに、最後の手順でスタックしました。

for pipe quote>

誰かがこれを説明することができれば私はそれをいただければ幸いです!

1
samjewell

より簡単な方法がある場合はコマンドラインを使用しないため、通常はNetBeansを使用してこの種の処理を実行しています。 NetBeansはgitをある程度サポートしており、[お気に入り]タブから任意のディレクトリ/ファイルで使用できます。

0
Vincent Cantin