LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Linux - General (https://www.linuxquestions.org/questions/linux-general-1/)
-   -   Bash script to read file and alter lines depending on create date (https://www.linuxquestions.org/questions/linux-general-1/bash-script-to-read-file-and-alter-lines-depending-on-create-date-572920/)

ChristianHein 07-28-2007 04:25 AM

Bash script to read file and alter lines depending on create date
 
Hey guys,

I need to have a bash script, but it's bothering me for days since I can't get it work.

It needs to do the following:
Read all user.conf files in a certain directory and it's subfolder (up to 1 level below).

The script will then read the files and search for the following line: date_created=Mon Jan 01 00:00:00 0000 if, the current date is 1 month ahead of the data in the file.

Or! The script looks at the files "last mofidied" date and check if it's older than 1 month


then the script should continue with the following.

Search for line: package=xxx and if it contains xxx then the script will change the following line: suspended=no to suspended=yes and saves the file.

OK, so now for my second thing, I need a batch script to reverse the above to as before the change.

I know this forum is not to script free scripts, and therefor; I am willing to pay. Also I would like to know if I don't get a loop when looking for the "last modified" date since the script changes the "modified date"!

If you already have such a script (doubtable) you can always mail me or add me on msn.

unSpawn 07-28-2007 04:36 AM

Hello and welcome to LQ.

I know this forum is not to script free scripts, and therefor; I am willing to pay.
Actually it is and there's posted a few every day. If somebody asks nicely there's more than a few people willing to help. You should however show you're willing to invest yourself. In other words asking for (good: "I'd like help with X", bad: "Gimme X") handouts is considered reply unworthy and asking for help with homework is not allowed by the LQ Rules. Willingness to pay is even worse IMNSHO because that's not what the LQ Community is about. If you want to pay please consider contributing to LQ.

That said
I need to have a bash script, but it's bothering me for days since I can't get it work.
posting what you got helps people help you quicker, easier.

ChristianHein 07-28-2007 04:44 AM

Ok that sounds fair unSpawn, The thing I already managed to get is to search for files, but that's off a tutorial posted here. I'm not trying to let others solve the problems, it's just way out of my league. LQ is a great support to the community (a community by itself) Really appreciate the things you do.

jschiwal 07-28-2007 05:12 AM

You can locate files prior to a certain day with the -mtime option of find. The first option could be -maxdepth <depth> to limit how many directory levels that find recurses.

If you extract the creating date from the file, use the "date" command with the -d '<extracted-date>' argument and the -s '%s' option to make subtraction easier. For example:
Code:

echo $(( ( $(date +'%s') - $(date +'%s' -d 'Mon Jul 01 00:00:00 2007'))/60/60/24 ))
You might want to print out the manpage for the date command:
man -t date | lpr

I would highly recommend installing the source for the findutils package and producing a PostScript or PDF manual from the texinfo source to produce the "Finding Files" (find.pdf) manual. The find command is one of those swiss army knife commands that you can't do without.

Extracting the dates from the files could be done in awk or sed. Grep is usually used to return a line containing the file.

ChristianHein 07-30-2007 01:08 PM

Ok, i now know to find the files, anyone else with some suggestions? I hate to be a bother, but i'd rather have someone make the script as i'm very new to this. Thanks in advance guys.

unSpawn 07-30-2007 04:18 PM

Code:

#!/bin/sh
# Purpose: doSomething
# Args: yes :-]
# Deps: Bash, GNU utils
# Run from: scheduler or manually

# Prepstage functions
progn=${0//*\//}
# Set debug mode when testing:
set -x

help() { echo "${progn}: --doSomething targetname"; exit 1; }
rand () { randVal=$(echo "$(date) ${RANDOM} $$"|sha1sum); RANDOMV="${randVal:0:40}"; }

# Where we lay our hat, that be our home.
TARGETDIR="/etc/certaindir"
if [ ! -d "$TARGETDIR" ]; then
        echo "${progn}: no DIR named \""$TARGETDIR"\"."
        exit 1
fi

# We like variables
if [ $# -eq 2 ]; then
        case "$1" in
                --doSomething)  # Let's do something on this target
                                shift 1; TARGET="$1"
                                if [ -z "$TARGET" ]; then help; fi     
                                ;;
                -h*|--h*)      # Somebody needs help
                                help
                                ;;
                *)              # Let's do nothing
                                help
                                ;;
        esac
else help
fi

# Set the date, we're not using %H%M%S resolution and we don't consider yrs either :-]
CHECKDATE=`date '+%a %d %b' --date="1 month ago"`

# Read all user.conf files in a certain directory and it's subfolder (up to 1 level below).
find "$TARGETDIR" -type f -iname \*.conf --maxdepth 1| while read FILEN; do
        # The script will then read the files and search for the following line:
        # date_created=Mon Jan 01 00:00:00 0000
        CONFDATE=`grep ^date_created= "${FILEN}"`; CONFDATE=(${CONFDATE//*=/})
        unset CONFDATE[3] CONFDATE[4]; CONFDATE="${CONFDATE[*]}"
        # if, the current date is 1 month ahead of the data in the file.
        if [ "${CONFDATE}" != "${CHECKDATE}" ]; then
                echo "${progn}: nothing to do in "${FILEN}" for "${TARGET}"."
        else
                # Let's do something
                # Search for line: package=xxx
                grep -q ^package="${TARGET}" "${FILEN}"
                case "$?" in
                        0)      # and if it contains xxx then the script will change
                                # the following line: suspended=no to suspended=yes and saves the file.
                                echo -en "${progn}: got "${TARGET}" in "${FILEN}": "
                                UMASK=027; DAC=($(stat -c '%a %g %u' "${FILEN}")); echo -en "changing: "
                                sed -e "s|suspended=no|suspended=yes|g" "${FILEN}" > "${FILEN}.${RANDOMV}" && \
                                install -u ${DAC[2]} -g ${DAC[1]} -m ${DAC[0]} "${FILEN}.${RANDOMV}" "${FILEN}" && \
                                echo "OK." || echo "FAILED, see "${FILEN}.${RANDOMV}"."
                                ;;
                        *)
                                ;;
                esac
        fi
done

exit 0

I. It may look OK but in essence it is just thrown together quickly. It's a kludge. It may or may not work: YMMV(VM) as usual.
II. Jschiwal gave you some solid hints about stuff you should read up on. I can imagine it's a daunting for a scripting newbie, but how else could you validate or correct a script someone has offered you? It may even Do Stuff that it doesn't advertise.
III. These could be helpful too:
Code:

function help() { echo "Bash scripting guides:
http://www.tldp.org/HOWTO/Bash-Prog-Intro-HOWTO.html
http://www.tldp.org/LDP/Bash-Beginners-Guide/html/index.html
http://www.tldp.org/LDP/abs/html/
http://wooledge.org/mywiki/BashFAQ?action=show&redirect=BashFaq
http://wooledge.org/mywiki/BashPitfalls"; }


ChristianHein 07-31-2007 10:27 AM

Thank you unspawn, it makes more sense to me now. Unfortunatly the script didn't work, as you've feared. I get the following error:

Code:

+ TARGETDIR=/usr/local/directadmin/data/users/
+ '[' '!' -d /usr/local/directadmin/data/users/ ']'
+ '[' 0 -eq 2 ']'
+ help
+ echo 'telehosting.sh: --doSomething targetname'
telehosting.sh: --doSomething targetname
+ exit 1


unSpawn 07-31-2007 12:41 PM

That's no error, that's *help*. It shows you what arguments you should provide.

ChristianHein 08-02-2007 03:51 AM

Ok i'm getting closer. But it appears that the script doesn't change anything after 1 month is passed.

Code:

+ read FILEN
++ grep '^date_created=' /usr/local/directadmin/data/users/testje/user.conf
+ CONFDATE='date_created=Thu May 26 18:27:32 2007'
+ CONFDATE=(${CONFDATE//*=/})
+ unset 'CONFDATE[3]' 'CONFDATE[4]'
+ CONFDATE='Thu May 26'
+ '[' 'Thu May 26' '!=' 'Mon Jul 02' ']'
+ echo 'telehosting2.sh: nothing to do in /usr/local/directadmin/data/users/testje/user.conf for .'
telehosting2.sh: nothing to do in /usr/local/directadmin/data/users/testje/user.conf for .

Note, at first the script didn't find any file so I had to hardcode the find command to: find /usr/local/directadmin/data/ -type f -iname user.conf Which I think saves some memory when executing the script.

unSpawn 08-02-2007 11:50 AM

Since you show persistence I rewrote the script a wee bit. (OK, the hardcoding part is stupid, I should use "getopt" instead but it'll do for now.) To see what changed save it and then "diff --side-by-side oldscript newscript | less". It does not remove the backups on failure but YMMV(VM) still.

Code:

#!/bin/sh
# Purpose: doSOmething
# Args: yes :-]
# Deps: Bash, GNU utils
# Run from: scheduler or manually

# Prepstage functions
progn=${0//*\//}
# Set debug mode when testing:
set -x

help() { echo "${progn}: --doSomething targetname"; exit 1; }
rand () { randVal=$(echo "$(date) ${RANDOM} $$"|sha1sum); RANDOMV="${randVal:0:40}"; }

# Where we lay our hat, that be our home.
TARGETDIR="/usr/local/directadmin/data"
if [ ! -d "$TARGETDIR" ]; then
        echo "${progn}: no DIR named \""$TARGETDIR"\"."
        exit 1
fi

# We like variables
if [ $# -eq 2 ]; then
        case "$1" in
                --doSomething)  # Let's do something on this target
                                shift 1; TARGET="$1"
                                if [ -z "$TARGET" ]; then help; fi
                                ;;
                -h*|--h*)      # Somebody needs help
                                help
                                ;;
                *)              # Let's do nothing
                                help
                                ;;
        esac
else help
fi

# Set the date value using epoch. You know, the stuff they take in the Tour De France ;-p
CHECKDATE=`date --date="1 month ago" +%s`

# Read all user.conf files in a certain directory and it's subfolder (up to 1 level below).
find "$TARGETDIR" -type f -iname \*.conf -maxdepth 1| while read FILEN; do
        # The script will then read the files and search for the following line:
        # date_created=Mon Jan 01 00:00:00 0000
        CONFDATE=`grep ^date_created= "${FILEN}"`; CONFDATE=(${CONFDATE//*=/})
        unset CONFDATE[3] CONFDATE[4]; CONFDATE=`date --date="${CONFDATE[*]}" +%s`
        # if, the current date is 1 month ahead of the data in the file.
        if [ -z "$CONFDATE" -o $CONFDATE -ge $CHECKDATE ]; then
                echo "${progn}: nothing to do in "${FILEN}" for "${TARGET}"."
        else
                # Let's do something
                # Search for line: package=xxx
                grep -q ^package="${TARGET}" "${FILEN}"
                case "$?" in
                        0)    # and if it contains xxx then the script will change
                                # the following line: suspended=no to suspended=yes and saves the file.
                                echo -en "${progn}: got "${TARGET}" in "${FILEN}": "
                                UMASK=027; DAC=($(stat -c '%a %g %u' "${FILEN}")); echo -en "changing: "
                                sed -e "s|suspended=no|suspended=yes|g" "${FILEN}" > "${FILEN}.${RANDOMV}" && \
                                install -u ${DAC[2]} -g ${DAC[1]} -m ${DAC[0]} "${FILEN}.${RANDOMV}" "${FILEN}" && \
                                { echo "OK."; rm -f "${FILEN}.${RANDOMV}"; } \
                                || echo "FAILED, see "${FILEN}.${RANDOMV}"."
                                ;;
                        *)
                                ;;
                esac
        fi
done

exit 0


ChristianHein 08-03-2007 03:46 AM

Hmmm i get the following error:
Code:

telehosting3.sh: got  in /usr/local/directadmin/data/users/testje/user.conf: changing: install: invalid option -- u
Try `install --help' for more information.
FAILED, see /usr/local/directadmin/data/users/testje/user.conf..

Not quite sure what it means though, I did change the scrpt a bit, i removed the -maxdepth since that didn't and instead i just moved the file 1 level above and that works fine. Also I don't see the package defined in the script. The package should really be "telehosting" instead of "xxx" which was just an example. All I see is
Code:

grep -q ^package="${TARGET}" "${FILEN}"
Where the target en filen refers to some code above.

So i was wondering, isn't it possible to write the script like:
find /usr/local/directadmin/data -name *user.conf*
touch (the above)
(open vi editor) ?date_created (compare to current date) some if and else statement which resolves to the below (if positive, 1 month old else die). Look for package=telehosting if it contains that package change suspended=no to suspended=yes
:wq! and repeat for the next file in line. Unfortunatly i'm not a big star when it comes to vi I know it's possible to replace a line when it contains a match but the date thing is still blurry to me.

unSpawn 08-03-2007 11:24 AM

Code:

#!/bin/bash -
# Purpose: doSomething
# Deps: Bash, GNU utils
# Run from: scheduler or manually
TARGETDIR="/usr/local/directadmin/data"; TARGET="telehosting"
CHECKDATE=`date --date="1 month ago" +%s`
find "$TARGETDIR" -type f -iname \*.conf | while read FILEN; do
 CONFDATE=`grep ^date_created= "${FILEN}"`; CONFDATE=(${CONFDATE//*=/})
 unset CONFDATE[3] CONFDATE[4]; CONFDATE=`date --date="${CONFDATE[*]}" +%s`
 if [ $CONFDATE -ge $CHECKDATE ]; then echo "nothing to do in ${FILEN}"
 else grep -q ^package="${TARGET}" "${FILEN}" && \
 sed -i -e "s|suspended=no|suspended=yes|g" "${FILEN}"; fi; done
exit 0

I'm done with this.

ChristianHein 08-04-2007 04:17 AM

Thank you so much unspawn, that worked for me :) I'll see what I can do about supporting this great website/community. Again thank you.

frenchn00b 08-04-2007 05:39 AM

Quote:

Originally Posted by ChristianHein
Hey guys,

I need to have a bash script, but it's bothering me for days since I can't get it work.

It needs to do the following:
Read all user.conf files in a certain directory and it's subfolder (up to 1 level below).

The script will then read the files and search for the following line: date_created=Mon Jan 01 00:00:00 0000 if, the current date is 1 month ahead of the data in the file.

Or! The script looks at the files "last mofidied" date and check if it's older than 1 month


then the script should continue with the following.

Search for line: package=xxx and if it contains xxx then the script will change the following line: suspended=no to suspended=yes and saves the file.

OK, so now for my second thing, I need a batch script to reverse the above to as before the change.

I know this forum is not to script free scripts, and therefor; I am willing to pay. Also I would like to know if I don't get a loop when looking for the "last modified" date since the script changes the "modified date"!

If you already have such a script (doubtable) you can always mail me or add me on msn.

awk is a wonderful tool, that can read write files / scripts / ...
http://www.gnu.org/software/gawk/manual/
learn this: it 's worth to do
you ll be glad of this powerful tool


All times are GMT -5. The time now is 11:56 PM.