2010-06-05 31 views
7

我有文件的目錄這樣如何重命名大量文件

a.JPG 
b.JPG 
c.JPG 

我想這樣

git mv a.JPG a.jpg 

我使用xargs的和其他工具,但似乎沒有試圖進行一些上班。

+0

您在下面的評論中提到您使用OS X.這意味着您(可能)正在使用保留大小寫的不區分大小寫的文件系統。因此,重命名中的問題是:你的文件系統將目標名稱視爲與目標名稱相同,並且由於Git通過文件系統工作,所以它也具有打開外殼的功能。 wbyoung下面的方法將通過將文件傳遞給可識別的中間名稱來解決問題。 – Jeet 2010-06-06 05:29:29

+0

注意:git 2.0.1解決了這個問題:http://stackoverflow.com/a/24979063/6309 – VonC 2014-07-27 08:06:44

回答

7

解決方案的核心將是使用一種工具/方法來自動執行批量重命名。您可以使用mv結合git add或只是git mv。無論哪種情況,如果您使用的是不區分大小寫的文件系統,則可能需要採取額外的步驟。因此,在我們處理批量重命名之前,討論如何處理案例可能會有所幫助。

大小寫敏感性

有些系統(或系統+文件系統組合般在Mac OS X *的HFS +文件系統的默認變體)的情況下保留,但不區分大小寫。在這樣的系統中,在進行只涉及更改名稱大小寫的重命名時,您可能需要小心。通常的解決方法是使用一個臨時名稱,這個名稱在兩個名稱之間的「橋樑」之間的差異不僅僅是大小寫(例如mv foo.JPG tmp && mv tmp foo.jpg)。

*可以在Mac OS X上使用區分大小寫的文件系統(包括HFS +的敏感變體 )。

從這裏開始,我將假設一個不區分大小寫的文件系統。

在Mac OS X上的mv命令可以在單個步驟中處理僅更換情況的重命名。如果與-i選項一起運行,它將提供「覆蓋?」提示,如果給出-n選項,它將跳過重命名。它只能通過「類似Unix系統的許多部分」的「足夠的繩索來掛斷你自己」的默認操作而獲得成功。

git mv命令是有點偏執的情況。它拒絕操作(「目標存在」錯誤),除非給出-f/--force選項。

# this will succeed, though it may fail/prompt if mv is aliased to use -n/-i 
mv foo.JPG foo.jpg 

# this will succeed 
mv -f bar.JPG bar.jpg 

# this will succeed but give a warning 
git mv -f quux.JPG quux.jpg 

批量重命名選項

Perl的重命名

所需的操作是很簡單的一個位shell腳本做,但你可以得到的Perl 重命名實用程序(一個喬丹·劉易斯提及)如果你需要做一些更復雜的事情。您可以嘗試rename from Debian's perl package,或者如果您覺得需要使用CPAN,則可以安裝File::Rename,其中包括重命名程序。

ksh的的bash的zsh破折號

下面使用不兼容POSIX的-ef。同樣,雖然在POSIX中指定-e,但它不是純Bourne兼容的。但他們都得到了廣泛的支持。

for f in *.JPG; do 
    ff="${f%.JPG}.jpg" 
    test -e "$f" || continue  # possible when not using nullglob 
    test "$f" != "$ff" || continue # possible when using nocaseglob 
    if test -e "$ff" && 
     ! test "$f" -ef "$ff"; then # possible on a case sensitive filesystem 
     echo "skipping <$f>: destination <$ff> exists and is distinct" 1>&2 
     continue 
    fi 

    # "mv" with "git rm" and "git add" 
    mv -f "$f" "$ff"  && 
    git rm --cached "$f" && 
    git add "$ff" 
done 

最後一節(MVgit的RMgit的添加)可能只有混帳MV更換:

# "git mv" 
    git mv -f "$f" "$ff" 

如果你非常關心如何重命名可能會在不區分大小寫的系統上失敗,那麼您可以使用臨時名稱:

# temp-based "mv" with "git rm" and "git add" 
    t="$ff.tmp"; while test -e "$t"; do t="$t.tmp"; done 
    mv -n "$f" "$t"  && 
    mv -n "$t" "$ff"  && 
    git rm --cached "$f" && 
    git add "$ff" 

或用混帳MV

# temp-based "git mv" 
    t="$ff.tmp"; while test -e "$t"; do t="$t.tmp"; done 
    git mv "$f" "$t" && 
    git mv "$t" "$ff" 

的zsh /&#xfeff; zmv

這其中需要-f兩個zmv混帳MV

zsh -c 'autoload zmv && $0 [email protected]' zmv -fp git -o 'mv -f' '(*).JPG' '$1 x.jpg' 

現在,你把它們都改名和Git的索引更新,你可以提交他們。

但是會使用區分大小寫的文件系統的其他Git用戶能夠檢查它們嗎?

git的結帳後爲例,僅重命名

如果有你的歷史的其他用戶,他們可能會仍然有JPG文件,當他們最終結賬(的後代),您與jpg提交文件。他們會發生什麼?

無論發生什麼事情,都不需要「重命名爲temp,提交,重命名爲final,commit」。git checkout在提交之間移動時不按順序應用提交。它通過將來自HEAD的索引和工作樹「合併」到新提交而起作用。這實際上意味着它在「HEAD」和索引/工作樹之間發現的非衝突性變化時直接「跳轉」到新提交。

在內部,Git視圖重命名爲刪除和添加。我沒有發現任何描述git結賬關於刪除和添加順序的行爲的文檔,所以我查看了源代碼。 git checkout在任何更新/添加(cmd_checkout - > switch_branches - > merge_working_tree( - > reset_tree) - > unpack_trees - >check_updates)之前處理所有刪除。

您可以測試了這一點後,就在您的命名承諾:

git checkout HEAD~ # note: detached HEAD 
# verify that the original names are back in place 
git checkout -  # back to your branch 
# verify that the new names are in place again 

混帳怪上的文件似乎表明一個可能犯:Make unpack-tree update removed files before any updated files,這是首次在Git的發佈1.5.6-RC0 (2008-06-18)。所以,儘管沒有記錄(?),但這種行爲是專門爲支持不區分大小寫的文件系統而實現的。

謝謝,Linus!

1

可能重命名爲* .somethingelse,然後重命名回* .JPG

2

使用標準的Linux rename(1) utility.一旦你重命名的文件,git的添加。

+0

使用「rename's/JPG/jpg /'* .JPG」 GIT是內容尋址的,所以重命名文件被自動檢測(只要內容保持不變)。 – tucuxi 2010-06-05 17:12:20

+0

我正在使用mac,所以我沒有重命名。 – 2010-06-05 17:16:37

+0

如果您希望git將提交存儲爲重命名,而不是作爲文件銷燬和文件創建,則需要使用'git add -A .'。 -A意味着檢查刪除(如果被跟蹤),不僅僅是文件創建。 – ivanxuu 2015-01-29 11:42:38

3

您是否可以更改文件的大小取決於您的文件系統。即使它在你的文件系統上工作,你也可能會導致其他人更新的問題。你最好重新命名它們,提交它們,然後重新命名它們。使用以下bash腳本將所有內容更改爲* .tmp:

for i in *.JPG; do mv $i ${i%.JPG}.tmp; done 

然後將它們全部移入git中。你可以使用類似的命令,但我建議檢查guess-renames這將有助於此舉。

然後使用類似的過程將它們全部重命名爲* .jpg。

+0

我認爲我會推薦'* .JPG'作爲'\'ls \'' – Dustin 2010-06-05 20:00:11

+0

好建議,我更新了使用* .JPG的答案。 – wbyoung 2010-06-05 20:07:33

+0

在提交之間移動時,Git不會重播每個中間變更集。移至新提交會更新當前HEAD /索引與目標提交之間已更改的文件。在多個階段提交重命名將無助於那些不能直接處理'mv foo.JPG foo.jpg'的機器的用戶(除非他們在移動到「on」提交時手動「訪問」「.tmp」提交重命名的另一面「)。 * git不需要* guess-renames *,'git add -u && git add '將拾取「重命名」而不是'git mv'(或者,只需使用'git mv'而不是'mv')。 – 2010-06-05 20:10:16