2017-01-21 75 views
0

由於需要使用重命名文件的手動複製和導入工具的組合來完成各種複雜的照片庫遷移,看起來我已經清理了大量類似結構的文件。這裏有一個例子:如何更改具有相似但不相同結構的所有文件名?

2009-05-05 - 2009-05-05 - IMG_0486 - 2009-05-05 at 10-13-43 - 4209 - 2009-05-05.JPG 

它應該是什麼:

2009-05-05 - IMG_0486.jpg 

其他文件具有相同的結構,但顯然個別日期和IMG號不同。

有沒有什麼辦法可以在終端中做一些命令行魔術來自動將這些文件重命名爲縮短/正確的版本?

+0

文件名應該保留的空間? – Inian

回答

2

我假設你可能有子目錄,並希望找到這個目錄樹中的所有文件。

這第一個代碼塊(可以放在腳本中)是「安全的」(什麼都不做),但會幫助你看看會做什麼。

datep="[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]" 
dir="PUT_THE_FULL_PATH_OF_YOUR_MAIN_DIRECTORY" 
while IFS= read -r file 
do 
    name="$(basename "$file")" 
    [[ "$name" =~ ^($datep)\ -\ $datep\ -\ ([^[:space:]]+)\ -\ $datep.*[.](.+)$ ]] || continue 
    date="${BASH_REMATCH[1]}" 
    imgname="${BASH_REMATCH[2]}" 
    ext="${BASH_REMATCH[3],,}" 
    dir_of_file="$(dirname "$file")" 
    target="$dir_of_file/$date - $imgname.$ext" 
    echo "$file" 
    echo " would me moved to..." 
    echo " $target" 
done < <(find "$dir" -type f) 

確保輸出是你想要的和期待。我無法測試你的實際文件,如果這個腳本沒有產生完全令人滿意的結果,我不承擔任何責任。如果您沒有可靠的,經過檢查的備份,請不要盲目地讓任何人(包括我)通過從互聯網上覆制和粘貼代碼來混淆您的寶貴數據。

一旦確認,決定是否要採取不用於測試任何機會寫上一些人的代碼有機會和替換echo開始與這三個連續的行:

mv "$file" "$target" 

注意文件名必須匹配到一個非常嚴格的模式才能進行處理,所以如果您注意到某些文件沒有被處理,那麼該模式可能需要修改。

1

假設他們都是確切相同的結構,空間和一切,你可以使用awk分割名稱使用空格作爲中斷點。這裏有一個快速和骯髒的例子:

#!/bin/bash 
output="" 

for file in /path/to/files/*; do 
    unset output #clear variable from previous loop 
    output="$(echo $file | awk '{print $1}')" #Assign the first field to the output variable 
    output="$output"" - " #Append with [space][dash][space] 
    output="$output""$(echo $file | awk '{print $5}')" #Append with IMG_* field 
    output="$output""." #Append with period 
    #Use -F '.' to split by period, and $NF to grab the last field (to get the extension) 
    output="$output""$(echo $file | awk -F '.' '{print $NF}')" 
done 

從那裏,像mv /path/to/files/$file /path/to/files/$output在文件循環將重命名文件最後一行。我會複製一些文件到另一個文件夾中進行測試,因爲我們正在處理文件操作。

所有的輸出分配行也可以合併到一行中,但它不太容易閱讀。

output="$(echo $file | awk '{print $1 " - " $5 "."}')""$(echo $file | awk -F '.' '{print $NF}')" 

不過你仍然需要一個文件循環。

1

假設你要的文件名轉換與第一日期和IMG *名稱,您可以運行該文件夾在以下方面:

IFS=$'\n' 
for file in * 
do 
printf "mv '$file' '" 
printf '%s' $(cut -d" " -f1,4,5 <<< "$file") 
printf "'.jpg" 
done | sh 
+0

請參閱[爲什麼你不應該解析ls(1)]的輸出(http://mywiki.wooledge.org/ParsingLs),相應地編輯你的答案,以避免得到反對票。這是行不通的 – Inian

+0

我已經加了'IFS = $'\ n''。我在我的本地機器上試過了,它運行了 –

+1

請參閱共享鏈接,_還注意到ls有時會損壞您的文件名數據(在我們的例子中,它將單詞「a」和「newline」之間的換行符轉換爲問號。有些系統改爲\ n)。在某些系統上,當它的輸出不是終端時,它不會這樣做,而在其他系統上它總是破壞文件名。總而言之,你真的不能也不應該相信ls的輸出是你想要使用的文件名的真實表示。所以不要._,我不打算投下它,但它不是最有效的方式,使用'find'! – Inian

相關問題