2010-09-08 61 views
45

我有一個包含約1,700個文件的文件夾。他們都被命名爲1.txt1497.txt等。我想重命名所有文件,以便所有文件名都是四位數字。Linux shell腳本將前導零添加到文件名

即,23.txt變成0023.txt

什麼是將執行此操作的shell腳本?或者一個相關的問題:我如何使用grep來匹配只包含\d.txt的行(即一個數字,然後是句點,然後是字母txt)?

這是我到目前爲止有:

for a in [command i need help with] 
do 
    mv $a 000$a 
done 

基本上,運行三次,命令那裏找一個數字,兩個數字,三位數字的文件名(與初始零的數量改變)。

+1

你應該用你使用[bash腳本的 – meagar 2010-09-08 22:17:07

+0

可能的複製殼標籤這個來填充文件名](http://stackoverflow.com/questions/55754/bash-script-to-pad-file-names) – 2015-10-01 07:41:38

+1

@CiroSantilli,順便說一句,我最近有人推遲了一個被關閉的重複作爲填充前導數字的邏輯以及稍後在名稱中填充填充數字的邏輯有所不同。 (因此,https://stackoverflow.com/questions/46993470/padding-filenames-with-zeros-in-bash目前標記了這個答案的愚蠢,*而不是*那個愚蠢的)。 – 2017-10-28 20:04:48

回答

46

嘗試:

for a in [0-9]*.txt; do 
    mv $a `printf %04d.%s ${a%.*} ${a##*.}` 
done 

根據需要更改文件名模式([0-9]*.txt)。


通用枚舉重命名不作任何初始設置文件名的假設:

X=1; 
for i in *.txt; do 
    mv $i $(printf %04d.%s ${X%.*} ${i##*.}) 
    let X="$X+1" 
done 

關於同一主題:

+0

這會爲每個已經有4位數的文件名輸出一串錯誤。在開始時加入foo會解決這個問題,但我不想那樣做。感謝這些鏈接。 – 2010-09-08 22:30:03

+0

對不起,「foo」...錯誤的複製/粘貼 – 2010-09-08 22:32:34

0

要只匹配單個數字的文本文件,你可以做...

$ ls | grep '[0-9]\.txt' 
+0

有沒有辦法從$ a中刪除'.txt'?我以前曾經好幾次想過。 – 2010-09-08 22:22:06

+0

是的,'$ {a%.txt}'會這樣做(或者'$ {a%。*}'來刪除任何後綴)。 – 2010-09-08 22:24:14

+0

如果你知道擴展之前的快速方法是通過sed來管道輸出,就像這樣:'ls | grep'[0-9] \。txt'| sed's/\ txt // g'' – LukeN 2010-09-08 22:24:34

11
for a in *.txt; do 
    b=$(printf %04d.txt ${a%.txt}) 
    if [ $a != $b ]; then 
    mv $a $b 
    fi 
done 
+0

感謝您的答案!基本上與另一個完全相同的時間相同。 – 2010-09-08 22:32:41

+1

@David:我的解決方案不會導致一堆錯誤。 :-P – 2010-09-08 22:33:29

+0

如果**輸入文件名沒有空格,則不會導致錯誤**。應該添加更多的引號來避免這種情況。 :) – 2017-10-28 19:52:44

7

一襯墊:

ls | awk '/^([0-9]+)\.txt$/ { printf("%s %04d.txt\n", $0, $1) }' | xargs -n2 mv 

如何用grep包含\ d.txt僅匹配線(IE 1位,則一個週期,那麼字母txt)?

grep -E '^[0-9]\.txt$' 
12

使用有時用Perl安裝renameprename在某些情況下)腳本,您可以使用Perl表達式來完成重命名。腳本跳過重命名,如果有名稱衝突。

下面的命令僅重命名具有四位或更少位數的文件,後跟「.txt」擴展名。它不會重命名不嚴格符合該模式的文件。它不會截斷包含多於四位數字的名稱。

rename 'unless (/0+[0-9]{4}.txt/) {s/^([0-9]{1,3}\.txt)$/000$1/g;s/0*([0-9]{4}\..*)/$1/}' * 

舉幾個例子:

Original Becomes 
1.txt  0001.txt 
02.txt  0002.txt 
123.txt  0123.txt 
00000.txt 00000.txt 
1.23.txt 1.23.txt 

其它給出的答案迄今將嘗試對包含非數字字符的文件名命名不符合模式的文件,產生誤差,進行重命名這會產生名稱衝突,請嘗試重新命名文件名稱中有空格的文件,以及可能存在的其他問題。

+0

Yagni。認真。誰關心包含空格或非數字字符的文件名,如果這不在問題的範圍之內?如果OP想寫一個通用腳本,他在問題中會這樣說,並且答案會相應地適應。 – 2010-09-15 19:41:16

+13

@Chris:我的答案經常做兩件事。一,他們試圖回答OP的問題。二,他們試圖提供可能對未來的觀衆有用的附加信息。 – 2010-09-16 00:17:36

+2

@ Dennis:謝謝你提供這個,最高評分的答案並沒有解決我的特殊問題,但正如你所指出的那樣,你提供了一個更廣泛和更廣泛的答案,這有助於。謝謝。 – 2013-04-26 08:48:22

4

假設您的文件夾中包含數據類型爲.dat的文件。就在這個代碼複製到一個文件名爲run.sh,運行chmode +x run.sh使其可執行文件,然後執行使用./run.sh

#!/bin/bash 
num=0 
for i in *.dat 
do 

    a=`printf "%05d" $num` 
    mv "$i" "filename_$a.dat" 
    let "num = $(($num + 1))" 
done 

這將所有文件轉換您的文件夾中filename_00000.datfilename_00001.dat

0

單行提示:

while [ -f ./result/result`printf "%03d" $a`.txt ]; do a=$((a+1));done 
RESULT=result/result`printf "%03d" $a`.txt 
1

此版本還支持在數字之前(之後)處理字符串。但基本上你可以做任何正則表達式匹配+ printf,只要你的awk支持它。它也支持文件名中的空白字符(除了換行符)。

for f in *.txt ;do 
    mv "$f" "$( 
     awk -v f="$f" '{ 
      if (match(f, /^([a-zA-Z_-]*)([0-9]+)(\..+)/, a)) { 
       printf("%s%04d%s", a[1], a[2], a[3]) 
      } else { 
       print(f) 
      } 
     }' <<<'' 
    )" 
done 
+0

我剛剛嘗試了上面的內容,它吹走了目錄中的所有文件並留下了一個文件「0000」。 – Ryan 2017-08-28 20:49:47

+0

@Ryan這意味着正則表達式不匹配你的目錄中的任何文件。你必須自定義正則表達式+ printf來完成任何事情。上面的代碼只是一個例子。 – rindeal 2017-08-31 20:50:15

+0

rindeal是正確的。當我糾正我的文件名正則表達式(我有空格)它的工作。與正則表達式不匹配的文件名仍然會移至'0000',這可能有點令人驚訝。如果您正在進行批量重命名並嘗試使用隨機腳本,那麼您最好有備份。 – Ryan 2017-09-01 20:24:29

0

爲了提供真實謹慎寫是正確的,即使在文件名的存在與空間的解決方案:

#!/usr/bin/env bash 

pattern='%04d' # pad with four digits: change this to taste 

# enable extglob syntax: +([[:digit:]]) means "one or more digits" 
# enable the nullglob flag: If no matches exist, a glob returns nothing (not itself). 
shopt -s extglob nullglob 

for f in [[:digit:]]*; do    # iterate over filenames that start with digits 
    suffix=${f##+([[:digit:]])}   # find the suffix (everything after the last digit) 
    number=${f%"$suffix"}     # find the number (everything before the suffix) 
    printf -v new "$pattern" "$number" "$suffix" # pad the number, then append the suffix 
    if [[ $f != "$new" ]]; then     # if the result differs from the old name 
    mv -- "$f" "$new"       # ...then rename the file. 
    fi 
done