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"
  • 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
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

| improve this answer | |
  • 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! – Busted 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 2:04
  • Cool, good to know! – Busted Jun 27 '19 at 6: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.

| improve this answer | |
  • It does seems easier, but i'm not using zsh currently.. thank you for trying to help (-: – Busted Jun 26 '19 at 16:14
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
| improve this answer | |
-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.

| improve this answer | |
  • 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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.