Search code examples
linuxbashshellcron

How to replace backup file with timestamp in its name without producing duplicates in Linux Bash (shell script)


#!/usr/bin/env bash

# usage: wttr [location], e.g. wttr Berlin, wttr New\ York

# Standard location if no parameters were passed
location=''
language=''
time=`date`
# Expand terminal display


if [ -z "$language" ]; then
  language=${LANG%_*}
fi

curl \
     -H -x "Accept-Language: ${language}" \
     -x wttr.in/"${1:-${location}}" |
head -n 7 |
tee /home/of/weather.txt |
tee -a /home/of/weather.log |
tee /home/of/BACKUP/weather_"$time".txt

#cp weather.txt /home/of/BACKUP
#mv -f /home/of/BACKUP/weather.txt /home/of/BACKUP/weather_"$time".txt

I'm very new to Linux Bash and Shell scripting and can't figure out the following. I have a problem with the shell script above. It works fine so far (curling ASCII data from website and writing it to weather.txt and .log). It is also in set in crontab to run every 5 minutes. Now I need to make a backup of weather.txt under /home/of/, in /home/of/BACKUP with the filename weather_<timestamp>.txt. I tried to delete (rm weather*.txt) the old timestamped files in /home/of/BACKUP and then copy and rename the file everytime the cronjob is running. I tried piping cp and mv and so on but somehow I end up with producing many duplicates as due to the timestamp the filenames are different or nothing at all when I try to delete the content of the folder first. All I need is ONE backup file of weather.txt as weather_<timestamp>.txt which gets updated every 5 minutes with the actual timestamp bit I can't figure it out.


Solution

  • If I understand your question at all, then simply

    rm -f /home/of/BACKUP/weather_*.txt
    cp /home/of/weather.txt /home/of/BACKUP/weather_"$time".txt
    

    cp lets you rename the file you are copying to; it doesn't make sense to separately cp and then mv.

    For convenience, you might want to cd /home/of so you don't have to spell out the full paths, or put them in a variable.

    dir=/home/of
    rm -f "$dir"/BACKUP/weather_*.txt
    cp "$dir"/weather.txt "$dir"/BACKUP/weather_"$time".txt
    

    If you are running out of the cron of the user named of then your current working directory will be /home/of (though if you need to be able to run the script manually from anywhere, that cannot be guaranteed).

    Obviously, make sure the wildcard doesn't match any files you actually want to keep.

    As an aside, you can simplify the tee commands slightly. If this should only update the files and not print anything to the terminal, you could even go with

    curl \
         -H -x "Accept-Language: ${language}" \
         -x wttr.in/"${1:-${location}}" |
    head -n 7 |
    tee /home/of/weather.txt \
        >>/home/of/weather.log
    

    I took out the tee to the backup file since you are deleting it immediately after anyway. You could alternatively empty the backup directory first, but then you will have no backups if the curl fails.

    If you want to keep printing to the terminal, too, probably run the script with redirection to /dev/null in the cron job to avoid having your email inbox fill up with unread copies of the output.