Reputation: 347
I have some 400 plain text files which are my writing pieces, all named as such,
A prose (June 30, 2013)
A sad story (Dec. 1, 2016)
The filename parts are mostly in Chinese or contain Chinese, but I suppose this is irrelevant. I want to rename them to be
130630_A prose
161201_A sad story
by using Bash script.
This is probably the first time I write a Bash script. I am reasonably familiar with c++, but I find Bash hard to learn. While I have basic familiarity with Vim's regex, I gather that Bash's regex is similar. I mainly relied on this reference on wildcards.
My attempt is as shown:
#! /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
}
It seems nothing happens. Some syntax is just my guess, so I think many steps many be wrong. But I cannot find on Stack Overflow an example as complicated as this, and I have no clear idea how to debug.
Upvotes: 1
Views: 149
Reputation: 347
There, there.
In the regex part, I have considered the possibility that in the parenthesis, there may be some other characters in between. For example, Something (new--Dec. 1, 2013).txt
The reader may modify to suit you need. There is a good reference for 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
Upvotes: 0
Reputation: 15461
You can use the date
command to convert the date part:
#!/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
With a recursive 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
Upvotes: 1