# Function checkfilename:
# Usage: checkfilename filename dayofweek [time]
# filename format: dayname..._timestart-timeend.extension
# (Underscores can optionally appear between the daynames.)
# Checks if filename contains dayofweek before the (last) underscore
# and that time is within the time range after the (last) underscore.
# If time is not given, the current time is used.
# Code notes:
# ${var#patt} Removes patt from beginning of $var.
# ${var%patt} Removes patt from end of $var.
# 10#num interprets num as decimal even if it begins with a 0.
checkfilename() {
local file day time days days2 times tstart tend
file="$1" # filename
day="$2" # day of week
# Check if the first part of the filename contains day.
days=${file%_*} # just the days
days2=${days/$day/} # Remove day from the days.
# If days == days2 then days didn't contain day; return failure.
if [ "$days" == "$days2" ]; then return 1; fi
# Get time from 3rd parameter or from date command
if (($# >= 3)); then time=10#"$3"
else time=10#$(date +%H%M); fi # get time in HHMM format
times=${file##*_}; times=${times%.*} # just the times
tstart=10#${times%-*}; tend=10#${times#*-}
# If second time is less than first time, add 2400
((tend < tstart)) && ((tend+=2400))
# If current time is less than first time, add 2400
((time < tstart)) && ((time+=2400))
# Check if time is between tstart and tend; return result.
((tstart <= time && time <= tend))
return $?
}
file="TuesdayThursdayMonday_2300-0018.txt"
dayofweek="Thursday"
checkfilename "$file" "$dayofweek" 0005 && echo yep
If the filename has a prefix to extract as well, it can be done like this:
file="1A_Monday_1800-1900.mp4"
ext=${file##*.} # remove from front longest string matching *.
file=${file%.*} # remove from back shortest string matching .*
prefix=${file%%_*} # remove from back longest string matching _*
days=${file#*_} # remove from front shortest string matching *_
days=${days%%_*} # remove from back longest string matching _*
times=${file##*_} # remove from front longest string matching *_
echo $file
echo $ext
echo $prefix
echo $days
echo $times
Note that in the match patterns, '*
' matches any number of any character. '.
' matches an actual period and '_
' matches an actual underscore. Others are '?
', matching any single character, [abcd]
matching any one of the contained characters, and [^abcd]
(or [!abcd]
), matching any character except one of the contained characters.
${var#patt}
expands to $var
with shortest patt
match removed from front.
${var##patt}
expands to $var
with longest patt
match removed from front.
${var%patt}
expands to $var
with shortest patt
match removed from end.
${var%%patt}
expands to $var
with longest patt
match removed from end.
A totally different method, using the IFS (input field separator) shell variable instead of the parameter expansions, splitting the fields on underscore and period into an array.
#!/bin/bash
# Function checkfilename:
# Usage: checkfilename filename dayofweek [time]
# filename format: prefix_dayname..._timestart-timeend.extension
# Checks if filename contains dayofweek between the underscores
# and that time is within the time range after the second underscore.
# If time is not given, the current time is used.
# Code notes:
# 10#num interprets num as decimal even if it begins with a 0.
# 'declare' also makes a variable 'local'
checkfilename() {
local file="$1" # filename
local day="$2" # day of week
local IFS='_.' # Split fields on underscore and period.
# Split and extract times and days.
local a=($file) # Split filename into array.
local prefix="${a[0]}" # Set prefix to the first field
local days="${a[1]}" # Set days to second field.
local times="${a[2]}" # Set times to third field.
local ext="${a[3]}" # Set ext to last field.
# echo -e "\nFile: $file"
# echo -e " Prefix: $prefix\n Days: $days\n Times: $times\n Ext: $ext"
# If days doesn't contains day, return failure.
if [ "$days" == "${days/$day/}" ]; then return 1; fi
# Get time from 3rd parameter or from date command
declare -i time
if (($# >= 3)); then time=10#"$3"
else time=10#$(date +%H%M); fi # Get time in HHMM 24-hr format.
declare -i tstart=10#${times%-*} tend=10#${times#*-}
((tend < tstart)) && ((tend+=2400))
((time < tstart)) && ((time+=2400))
# Check if time is between tstart and tend; return result.
((tstart <= time && time <= tend))
return $?
}
file="1A_TuesdayThursdayMonday_2300-0018.txt"
dayofweek="Thursday"
checkfilename "$file" "$dayofweek" 0005 && echo pass1
checkfilename "$file" "$dayofweek" 0025 || echo pass2
dayofweek="Saturday"
checkfilename "$file" "$dayofweek" 0005 || echo pass3