簡體   English   中英

嘗試使用 Bash 正則表達式自動重命名文件名中的日期

[英]Attempt to automatically rename date in filenames, using Bash regex

我有大約 400 個純文本文件,它們是我的寫作作品,全部都是這樣命名的,

A prose (June 30, 2013)
A sad story (Dec. 1, 2016)

文件名部分大部分是中文或包含中文,但我認為這無關緊要。 我想將它們重命名為

130630_A prose
161201_A sad story

通過使用 Bash 腳本。

這可能是我第一次編寫 Bash 腳本。 我對 C++ 相當熟悉,但我發現 Bash 很難學。 雖然我基本熟悉 Vim 的正則表達式,但我認為 Bash 的正則表達式是相似的。 我主要依賴於通配符的參考

我的嘗試如圖所示:

#! /usr/bin/env bash

EXT=.txt


for name_old in "*${EXT} */*${EXT} */*/*${EXT}"; do
   str_title=$(expr "${name_old}" : '\(.*\)(.*).*')
   str_date=$(expr "${name_old}" : '.*(\(.*\)).*')
   str_y=$(expr "${str_date}" : '.*\([0-9]*\).*')
   str_m=$(expr "${str_date}" : '.*\([a-zA-Z]*\).*')
   str_d=$(expr "${str_date}" : '.*\([0-9]*,\).*')

   if [ ${#str_y} -eq 0 ] || [ ${#str_m} -eq 0 ] || [ ${#str_d} -eq 0 ] ; then
      continue
   fi

   name_new="${name_new}${str_y:2:3}"

   convert_month "${str_m}" hold
   name_new="${name_new}hold"

   if [ ${#str_d} -eq 1 ]; then
      name_new="${name_new}0${str_d:0:0}"
   elif [ ${#str_d} -eq 2 ]; then
      name_new="${name_new}${str_d:0:1}"
   fi

   name_new="${name_new}_${str_title}"
   mv name_old name_new
done

function convert_month
{
   if [ "$(expr "$(1)" : '.*\(Jan\).*')" -ne "" ]; then
      $(2)=01
   # ... omitted for brevity
   elif [ "$(expr "$(1)" : '.*\(Dec\).*')" -ne "" ]; then
      $(2)=12
   fi
}

好像什么都沒發生。 有些語法只是我的猜測,所以我認為很多步驟都是錯誤的。 但是我在 Stack Overflow 上找不到這么復雜的例子,我也不清楚如何調試。

您可以使用date命令轉換日期部分:

#!/usr/bin/env bash
for file in *.txt; do
  str_date="$(grep -oP '\(\K[^\)]+'  <<< "$file")";
  date_str=$(date -d"$str_date" +%y%m%d);
  alphachars="${file/ (*/}";
  ext="${file##*.}";
  mv "$file" "${date_str}_${alphachars}.${ext}";
done

通過遞歸find

#!/usr/bin/env bash
find . -maxdepth 3 -type f -name '*.txt' | while read -r file; do
  filename=${file##*/};
  dir=${file%/*};
  str_date="$(grep -oP '\(\K[^\)]+'  <<< "$filename")";
  date_str=$(date -d"$str_date" +%y%m%d);
  alphachars="${filename/ (*/}";
  ext="${filename##*.}";
  mv "${file}" "${dir}/${date_str}_${alphachars}.${ext}";
done

那里,那里。

在正則表達式部分,我已經考慮了括號中可能還有其他一些字符的可能性。 例如, Something (new--Dec. 1, 2013).txt讀者可以根據需要進行修改。 Bash regex 有一個很好的參考

#! /usr/bin/env bash

# To renames, say, `Something (Dec. 13, 2016).txt` to `161213_Something.txt`
# First parse the `()`-enclosed part in filename, called `str_date`
# if `2016` is a substr of DATE, set YY
# if `Dec` is a substr of DATE, set MM
# if `13,` is a substr of DATE, set DD

# first define functions

function convert_year
{
   local tmp=$1
   if [ "${#tmp}" -eq 4 ]; then
      echo "${tmp:2:2}"
   fi
}

function convert_month
{
   if [ "${1}" == "Jan" ]; then
      echo "01"
   elif [ "${1}" == "Feb" ]; then
      echo "02"
   elif [ "${1}" == "Mar" ]; then
      echo "03"
   elif [ "${1}" == "Apr" ]; then
      echo "04"
   elif [ "${1}" == "May" ]; then
      echo "05"
   elif [ "${1}" == "une" ]; then
      echo "06"
   elif [ "${1}" == "uly" ]; then
      echo "07"
   elif [ "${1}" == "Aug" ]; then
      echo "08"
   elif [ "${1}" == "Sep" ]; then
      echo "09"
   elif [ "${1}" == "Oct" ]; then
      echo "10"
   elif [ "${1}" == "Nov" ]; then
      echo "11"
   elif [ "${1}" == "Dec" ]; then
      echo "12"
   fi
}

function convert_day
{
   local tmp=$1
   if [ ${#tmp} -eq 2 ]; then
      echo "0${tmp:0:1}"
   elif [ ${#tmp} -eq 3 ]; then
      echo "${tmp:0:2}"
   fi
}

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # 

EXT=.txt

find . -maxdepth 3 -type f -name '*.txt' | while read -r name_file; do
   if [[ $name_file =~ (.*)/([^/_]*)_*\(.*([A-Za-z]{3}).*_([0-9]*,).*([0-9]{4})\).*${EXT} ]]
   then
       yy=$(convert_year "${BASH_REMATCH[5]}")
       mm=$(convert_month "${BASH_REMATCH[3]}")
       dd=$(convert_day "${BASH_REMATCH[4]}")

       name_new="${BASH_REMATCH[1]}/${yy}${mm}${dd}_${BASH_REMATCH[2]}${EXT}"
       mv ${name_file} ${name_new}
   fi
done

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM