1

I've totally hacked together this script and I hope to get some corrections, or some insight into a much simpler version which I know is possible...

I want to loop through a named dir and check each subdir if it contains any subdirs that are X minutes old, and if so delete the old subdir. Each eligible subdir will only contain 1 symbolic link.

For this structure /var/www/flash/avmin/{$usr_id}/{$timestamp}/{->symlink}

I want to preserve /{$usr_id} but delete all /{$timestamp} if +12 hours old, and I assume this means I need to empty it before deleting it.

Because it is likely that /{$usr_id} will be created in the same server instance when $timestamp and the symlink are created, I must loop through each /{$usr_id} subdir and test conditions from there.

I will make this script run every 12 hours with Cron running as root, therefore within one 24 hour period all symlinks will be assured to be clean.

Note there may be several {$timestamp} subdirs in ../{$usr_id}, but each subdir will contain only 1 symlink and nothing else.

I sense this could be one or two lines of code without the for...in and simply using find inside avmin using (-maxdepth 2) and a time condition of X hours (or X mins) right???

#!/bin/bash

for i in /var/www/flash/avmin/*
do
    cd "$i"
    for xdir in "$i"
    do
        if [ "$xdir" type d -cmin +60 ]; then
            find . -maxdepth 2 -type L -cmin +60 -exec rm {} \
        "$xdir" -type d -cmin +60 -exec rm {}
    fi
        done
done
exit

I saw a "similar question" which has given me an idea here

Community
  • 1
  • 1
bellasys
  • 255
  • 1
  • 8
  • Hello. Please edit your question to first clearly state what you want to do: go into which dir(s), and there remove which symlinks? (those that are older than x days? hours? seconds?). And in your script I find weird right now: [ "$xdir" type d -cmin +60 ] which makes no sense, and also once whatever that's supposed to be, you then "find ." instead of "find $xdir", which I find weird as well... – Olivier Dulac Jan 23 '14 at 16:45
  • Not weird at all- just bad scripting :) that's why I'm asking – bellasys Jan 23 '14 at 17:46
  • Welcome to scripting :) I recommend you start with the whole content of : http://linuxcommand.org/ (learn about the commands in the linux world, and then about the basics of shell scripting). Then, when you have questions, refer first to the following: http://mywiki.wooledge.org/BashFAQ and http://mywiki.wooledge.org/BashPitfalls . Remaining scripting/programming questions will be gladly asked in http://StackOverflow.com (but commands more about unix/linux commands more on : http://unix.stackexchange.com or http://serverfault.com (+ expert security Q on http://security.stackexchange.com) – Olivier Dulac Jan 23 '14 at 18:41

1 Answers1

1

I am not sure at all I'm answering the right question (please edit your question to clearly state what you need to be done, as right now the example script is making little sense...]

What I guessed so far:

1) you want to look, for every dirs 1 level underneath /var/www/flash/avmin/*/ , only those directories older than 60 minutes

2) then you want, inside those dirs, to delete all links older than 60 minutes?

With these guesses:

#!/bin/bash

export NBMIN=60

#find all subdirs jsut underneath each /var/www/flash/avmin/*/ that are $NBMIN minutes old
for xdir in $(find /var/www/flash/avmin -type d -mindepth 2 -maxdepth 2 -cmin +${NBMIN} ) 
do
   #for those dirs, delete symlinks "just underneath", that are older than $NBMIN minutes
   find "$xdir" -mindepth 1 -maxdepth 1 -type L -cmin +${NBMIN} -exec echo rm '{}' \;
   #and then if there is nothing else in that dir, delete it:
   command rmdir "$xdir" #without -f and -r... will only remove "$i" directory if it's empty!
done

Of course this will only work if every dirs & files are just "normal" names (ie, do not contain spaces, and other weird characters like "newline" or others)... Stephane will probably pop up an answer with Zsh "**/" niceties ;)

I'm not sure that is what you want (and please test it... and only remove the "echo" (so "echo rm" becomes "rm") once you are 100% sure that it only lists the files you wanted to see gone ! (for example, I'm not sure you only want to look inside directories older than 60mn ?)

Olivier Dulac
  • 3,695
  • 16
  • 31
  • Yes- only remove dirs+contents > NBMIN old. I reviewed my question and can see that it is much less clear than I thought- will edit, thx. I believe you have answered the question I asked... quick question- why did you need to quote (code) rm '{}' ? and what is the function of /; in the first find statement line? I mean is the ; really necessary, and I guess I'm confused what / does... – bellasys Jan 23 '14 at 17:15
  • 1
    I am using your script- I credited you by name in my server file. Here's what I found helpful in your answer: you're showing me the proper way to reference $xdir in each statement, since it is really the crucial condition. No way would I have figured to use the last line ( command rmdir "$xdir" ). Now I will study.. – bellasys Jan 23 '14 at 18:07
  • 1
    to explain why I used "command rmdir" : `command something` : in bash, will bypass any "alias" or function" named `something`, so that you know you run the `something` binary(or script) found by the shell by looking in the $PATH... for example: `alias ls="echo NO"; function ls { echo "AhAh" ; } ; ls ; \ls ; command ls` : 'ls' and '\ls' will run the function, and will show 'Ahah'. command ls will run /bin/ls on the current directory, bypassing both function AND alias – Olivier Dulac Jan 23 '14 at 18:21
  • 1
    to answer your questions : '\;' is "escaping" the ';' so that the shell doesn't treat it as a command separator (; is a command separator)... instead, as it is escaped with a backslash, the shell treat it as a normal character, and therefore it is "sent" to the find command, which uses it as the "end of -exec delimiter" (ie, to know where the -exec ends) – Olivier Dulac Jan 23 '14 at 18:27
  • 1
    and I also quote the {} for the same reason, so that the shell treat them as simple characters, and not as a `{}` command group... it will all make sense when you start reading about shell and shell scripting ^^ . But in bash, you can for example do: `cd /tmp ; pwd ; { cd / ; ls ; } >/dev/null ; pwd` # this will: go in /tmp, then show it (pwd=print working directory), then IN THE CURRENT SHELL do `cd / ; ls` but will redirect all this command group output into /dev/null (so you will not see it!), and then, as it is now in "/" because the "cd /" was done in the current shell, it will show "/". – Olivier Dulac Jan 23 '14 at 18:31
  • 1
    compare with : (), that run commands in a subshell: `cd /tmp ; pwd ; ( cd / ; ls ; ) >/dev/null ; pwd` : now the last "pwd" will print "/tmp"... because the whole "cd / ; ls" happened in a subshell, and not in your current shell, so in the current shell you still are in /tmp – Olivier Dulac Jan 23 '14 at 18:32
  • 1
    and one more thing : $( .... ) : will run "....." and replace the whole $( .... ) by the output of ".......". So for example: `mydir=$(pwd) ;` will place inside "mydir" variable the working directory outputed by "pwd". Whereas : `mydir=pwd`, will put "pwd" (those 3 caracters) in the variable mydir. $(...) execute ... and is then replaced by "..." output. I use it to have the "for i in ....", .... being the output of the whole $(find .......), ie, a list of directories with the right criterions – Olivier Dulac Jan 23 '14 at 18:35
  • 1
    yes, it's things like you mention I will be studying, and it was helpful to have them pointed out referencing the code- – bellasys Jan 23 '14 at 18:36
  • EDIT: I had to change ... -type L ... to ... -type l ... to get it to work. I'm also going to test (code) command rmdir "$xdir" -rf # to see if it will remove the dir and link in one shot, further simplifying the script since that's really what I want. – bellasys Jan 23 '14 at 21:23
  • avoid `-rf` option of rm, or be absolutely SURE that you only do it in the right directory! – Olivier Dulac Jan 24 '14 at 11:38
  • In my final script I am not using -rf, and it currently working very well on my production server. – bellasys Jan 24 '14 at 18:31