2016-04-27 132 views
3

我有一堆只是一個unix時間的文件。問題是他們的文件名是millis,掃描目錄的程序希望他們在幾秒鐘內完成。所以我需要重命名所有文件,以刪除.txt擴展名前的最後3位數字。 IE:Bash Regex重命名文件

1461758015598.txt - > 1461758015.txt

我是新來的正則表達式和bash,所以我不知道如何做到這一點。

+0

一故障保護python的替代工作遞歸:http://stackoverflow.com/a/39698169/191246 – ccpizza

回答

3

這裏有一種方法:

for f in *.txt; do 
    mv "$f" "${f/[0-9][0-9][0-9].txt/.txt}" 
done 

dodone之間,它看起來在一次一個文件,當前文件的名稱是在放慢參數f"$f"是該參數的值,保持不變。 "${f/[0-9][0-9][0-9].txt/.txt}"是應用替換的參數的值:替換「三位數後跟.txt」,僅爲.txt

正如@anubhava指出的那樣,如果你不止一次運行它,它將會使文件名數量減少數字,所以不要那麼做。您可以通過收緊glob模式來使其變得冪等。這是一個有點笨拙:

for f in [0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9].txt; do 
    mv "$f" "${f/[0-9][0-9][0-9].txt/.txt}" 
done 

所以,你可能需要使用外部工具,使其更爲緊湊(假設有目錄中沒有空格或換行符的任何文件名):

for f in $(ls -1 | egrep '^[0-9]{13}\.txt$'); do 
    mv "$f" "${f/[0-9][0-9][0-9].txt/.txt}" 
done 

您可以通過使用while read循環減少限制只是「不換行」:

ls -1 | egrep '^[0-9]{13}\.txt$' | while read f; do 
    mv "$f" "${f/[0-9][0-9][0-9].txt/.txt}" 
done 
+4

OP需要只運行它一次,或者它也會重命名「1461758015.txt」爲「1461758.txt」,然後「1461758.txt 'to'1461.txt' – anubhava

+0

If OP的使用bash無論如何都是使用'ls +([0-9]).txt |的extglob egrep ...'可能更安全,而且在大型目錄中性能更高。 – ghoti

0

馬克的回答涵蓋了多種選擇。

但是,如果你想要的東西遞歸,我會用find基礎的解決方案是這樣走:

find -E . -regex '.*/[0-9]{13}\.txt' -exec \ 
    sh -c 'set -; mv -v "$0" "${0%???.txt}.txt"' "{}" \; 

注:

  • 我使用FreeBSD的,其中有一個-E選項告訴-regex使用ERE。如果您使用的是較舊的操作系統,則可能需要將ERE轉換爲BRE。
  • ERE堅持13位數字。如果您不止一次運行轉換,這可以讓您免受anubhava對增加減少的擔憂。
  • 對於參數擴展,我使用${..%..}而不是${../../},這使得此POSIX兼容,而不是依賴於bash。 (它當然也會在bash中工作,但它並不需要)
  • 您可能想知道爲什麼匹配只會刪除單個通配符而不是數字。這很好 - 我輸入起來更容易,並且我們已經將文件名限制設置爲find的選項的一部分。

如果您更願意避免使用find但仍然想要的東西在bash遞歸,您可以使用globstar選項:

shopt -s globstar extglob 
for f in **/+([0-9]).txt; do 
    [[ $f =~ ^[0-9]{13}\.txt$ ]] && mv -v "$f" "${f%...\.txt}.txt" 
done 

注意globstar取決於bash的版本4