5

If I have a folder of files with their filenames as the date they were created:

2019_04_30.txt
2019_04_15.txt
2019_04_10.txt
2019_02_20.txt
2019_01_05.txt

How would I compare the files names against todays current date

$ date "+%Y_%m_%d"
>>> 2019_04_30

If the file names date is greater than 30 days then delete it. I would expect to end up with

2019_04_30.txt
2019_04_15.txt
2019_04_10.txt

I don't have to follow this naming convention, I could use a more suitable date format.

2
  • You can use YYYY-MM-DD for your filenames, it would help when using "date" functions then
    – darxmurf
    Apr 30, 2019 at 11:09
  • 1
    It's a lot simpler to use the modification time on the files - find . -iname 20??_??_??.txt -type f -mtime +30 -exec rm -f {} \;
    – symcbean
    Jan 17, 2021 at 23:31

4 Answers 4

6

Here is a bash solution.

f30days=$(date +%s --date="-30 days")
for file in 20*.txt; do
    fdate=$(echo $file | tr _ -)
    fsec=$(date +%s --date=${fdate/.txt/})
    if [[ $fsec -lt $f30days ]]; then
        echo "rm $file"
    fi
done

I ended it with "echo rm $file" instead of really deleting your files, this will test the result before.

1
  • You don't have to convert file names. yyyy-mm-dd strings have a property that they're alphabetically ordered. So just do: f30days=$(date +%F --date="-30 days"); for file in 20*; do; if [[ $file -gt $f30days ]]; then; echo "rm -rf "$file""; fi; done.. Sorry for the oneliner, comments doesn't allow newlies. Jan 17, 2021 at 23:25
5

With zsh:

zmodload zsh/datetime
strftime -s start '%Y_%m_%d.txt' $((EPOCHSECONDS - 30*86400))
echo -E rm -i 2*.txt(e:'[[ $REPLY > $start ]]':)

Remove the echo -E when happy.

On a GNU system and with the GNU shell (bash), you could do something approaching with:

start=$(date -d '30 days ago' +%Y_%m_%d.txt)
list=()
shopt -s nullglob
for file in 2*.txt; do
  [[ $file > $start ]] && list+=("$file")
done
if (( ${#list[@]} > 0)); then
  echo -E rm -i "${list[@]}"
fi
1

This does not fit your answer exactly but I think you if work through the logic you will find many ways to work through your problem.

This is based on me wanting to check to see if a backup was made within the last 14 days based on the filename format "%username%.Backup.YEAR.MONTH.DAY.time.HOURS.MINUTES"

I believe in its current state it will fail to produce the correct result if you go above 28 days due to not looping through the if statement inside setlocal until days is no longer less than 1.

set year=%date:~10%
set month=%date:~4,2%
set day=%date:~7,2%
set /a day-=14
set /a leapyear=!(%year%%%4)
set numdays=31 28 31 30 31 30 31 31 30 31 30 31
if %leapyear%==1 set numdays=31 29 31 30 31 30 31 31 30 31 30 31

setlocal enabledelayedexpansion
    if %day% lss 1 (
        set /a month-=1
        if !month! lss 1 (
            set /a year-=1
            set /a month+=12
        )
        set mcount=0
        for %%A in (%numdays%) do (
            set /a mcount+=1
            if !mcount!==!month! set /a day+=%%A
        )
    )
    set day=0%day%
    set month=0%month%
endlocal & (set day=%day:~-2%)& (set month=%month:~-2%)& (set year=%year%)

for /f "tokens=3,4,5 delims=." %%A in ('dir /b /a:d /o:-n "%backuppath%" ^| findstr /r "%username%.Backup.*"') do (
    if %year%%month%%day% lss %%A%%B%%C (
        goto endofscript
    )
)
1
  • When did Linux & Unix start support the DOS CMD shell?
    – symcbean
    Jan 17, 2021 at 23:32
0

yyyy-mm-dd strings have a property that they're alphabetically ordered. So just do:

fdate=$(date +%F --date="-30 days")
for file in 20*; do
    if [[ $file =~ [0-9]{4}-[0-9]{2}-[0-9]{2} && $file -gt $fdate ]]; then
        rm -rf "$file"
    fi
done

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.