2

I am looking for a way to delete folders that are older than 7 days, but always have 20 newest folders. similar named folders with _SAME_NAME_@tmp should be deleted as well.

I'm stuck with making sure it really will be 20 folders at the end, and it will not be deleted after a month has past. I am also struggling with the nested while loop syntax. Many thanks in advance.

#!/bin/bash

folders=`ls -A /folder/folder1  | sort -n > /tmp/test.txt`
NUMofFolders=`wc -l /tmp/test.txt | awk '{print $1}'`

if [ $NUMofFolders -lt 20 ] ;
then
 echo "Only 20 folders exist"
 exit 1
else
echo "Runing with the script"

fi

input="/tmp/test.txt"
FolderPATH="/folder/folder1"
count=$(find $Folders -maxdepth 1 -type d -mtime +7 -printf '%Ts\t%P\n' -exec egrep -v "*@tmp" '{}' + | wc -l)

while IFS= read -r line ;
do
while [ "$count" -gt "20" ] ;
do
  find /folder/folder1/"$line" -maxdepth 1 -type d -mtime +7 -printf '%Ts\t%P\n' {} \;
      do
        find $FolderPATH -maxdepth 1 -type d -mtime +7 -print -delete -quit
        count=$((--count))
        rm -rf $FolderPATH@tmp

      done
  done < "$input"
Jeff Schaller
  • 67,283
  • 35
  • 116
  • 255
soBusted
  • 791
  • 2
  • 7
  • 12
  • For testing, I used a loop such as this, in case it helps future testing: for d in {20180301..20180331} ; do mkdir "$d" && touch -d "$d" "$d"; done – Jeff Schaller Jun 26 '19 at 14:16

4 Answers4

1

You'll want to use stat to get the mtime of the dirs, don't parse ls

seven_days=$(date -d '7 days ago' '+%s')
stat -c "%Y %%n" /folder/folder1/*/ | sort -nr | tail -n +20 | while read -r mtime name; do
    if (( mtime < seven_days )); then
        echo "remove directory $name"
    fi
done

stat will output the mtime and the folder name.
Then, sort by mtime from newest to oldest.
Then, ignore the top 20 results.
Then, in a loop, compare the mtime of the folders to the time a week ago, and decide to keep or remove.

If the output is finding the right directories, change the echo line to actually remove them

glenn jackman
  • 85,964
  • That seems like an idea in the right direction. I found that /folder/folder1// was having 1 / too many --> /folder/folder1/ , thank you for you help! – soBusted Jun 26 '19 at 16:41
  • 1
    When you have a glob with a trailing slash, the results of the expansion are limited to directories only. Your question was about deleting folders, so I wanted to explicitly exclude files. – glenn jackman Jun 27 '19 at 02:04
  • Cool, good to know! – soBusted Jun 27 '19 at 06:39
1

I see you tagged , but just in case zsh is an option, this zsh script might make your life easier:

zmodload zsh/mapfile
startingdirs=( ${(f)mapfile[/tmp/test.txt]} )
for dir in $startingdirs
do
  deleteme=( $dir/*(N/m+7om[21,-1]) )
  rm -r $deleteme $^deleteme'@tmp'
done

This loads the mapfile function (credit) to read the list of starting directories from your input file, /tmp/test.txt, into an array. We then loop over that array of starting directories and initialize another array of candidate directories to delete. That list of directories-to-delete is the result of a wildcard expansion under the starting directory with a set of "glob qualifiers":

  • N -- sets the NULL_GLOB option for this pattern; if no files match (because none are old enough, say), the resulting array will be empty
  • / -- restricts the matches to directories
  • m+7 -- restricts the matches to those that have a modification time more than 7 days ago
  • om -- "orders" or sorts the resulting list by modification time, newest to oldest
  • [21,-1] -- splices out the portion of the resulting list from item number 21 through the end of the list, resulting in the oldest files beyond the 20th.

We then call rm -r on the resulting directory list along with the expansion of that list with @tmp appended. Thanks to Stéphane's answer here for a demonstration of the ^ concatenation operator, which here appends the single-quoted string @tmp to each element of the array.

Jeff Schaller
  • 67,283
  • 35
  • 116
  • 255
0

After some painful iterations, I finally found a solution that work for me:

#!/bin/bash

# Inserting folders names in a file by reverse order - new at the starnputt
ls -A /tmp/lab  | egrep -v "*@tmp" | sort -nr > /tmp/test.txt

# Removing 20 newst folders.
sed '1,20d' /tmp/test.txt > /tmp/new_removed.txt

# Checking if there are more than 20 folders, if not- exit.
NUMofFolders=`wc -l /tmp/new_removed.txt | awk '{print $1}'`

if [ $NUMofFolders -lt 20 ] ;
then
 echo "Only 20 folders exist"
 exit 1
else
echo "Running with the script"

fi

#Deleting files, after checking it is older than 7 days
input="/tmp/new_removed.txt"
FolderPATH="/tmp/lab"

while IFS= read -r line ;
do
if [[ $(find "$FolderPATH/$line" -maxdepth 1 -type d -mtime +7 -print -exec rm -rf {} +) ]]; then
echo "files Deleted"

fi
done < "$input"

unset NUMofFolders
unset input
unset FolderPATH
unset line
soBusted
  • 791
  • 2
  • 7
  • 12
-1

Below script will work fine for you

#!/bin/bash
count=`find . -maxdepth 1 -type d | wc -l`
if [[ $count > 20 ]]
then
  under_7days=`find . -maxdepth 1 -type d -daystart -mtime -7 | wc -l`
  if [[ $under_7days >= 20 ]]
  then
    find . -maxdepth 1 -daystart -mtime +7 -exec rm -rvf {} \;
  else
    echo "Since total directories which created under 7 days is $under_7days"
  fi
elif [[ $count <= 20 ]]
then
  echo "Number of folders exsists in the path is $count"
fi

I have used maxdepth 1 so it will consider only the directories in the current path.

  • 1
    if we have 25 folders in the path which were created 7 days ago, this code will keep only 5 instead of 20. – Siva Jun 26 '19 at 12:56
  • @msp9011 Kindly check and remove down vote – Praveen Kumar BS Jun 26 '19 at 13:13
  • hope it won't delete if we have 100 folders and only 5 were created less than 7 days.... and I'm not the one downvoted... – Siva Jun 26 '19 at 13:37
  • At a quick glance there are few more issues: your code also will delete files since you don't limit find by a filetype. In under_7days you have -type but miss the actual type. – rush Jun 26 '19 at 13:55
  • -daystart is an option that modifies the corresponding mtime option; you still need to use -mtime in there. There's a logic mismatch here where you require more than 20 "under 7 days old" files before you remove anything. I think the OP could have 20+ files over 7 days old and would want to remove the oldest of those (keeping the 20 newest of those). – Jeff Schaller Jun 26 '19 at 14:15
  • Added mtime in script – Praveen Kumar BS Jun 26 '19 at 16:34
  • Thank you for trying to help! – soBusted Jun 27 '19 at 06:42