[英]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.