繁体   English   中英

bash脚本根据修改的文件日期删除目录

[英]bash script to remove directories based on modified file date

我希望创建一个 bash 脚本,它递归地遍历目录,并从树的最末端开始,按日期检查文件。 如果最新的文件早于 90 天,请上一级目录并检查相同的内容。 如果没有超过 90 天的文件,请删除根目录。

例子

/ftpdir/Site1/folder1/folder2

如果文件夹 2 没有更新的文件,但文件夹 1 有,则删除文件夹 1,但保留 Site1

我已经在AutoIT编写了这个,但现在需要它作为 bash 脚本,我有点迷茫。

谢谢

编辑:我以为我很清楚,但让我澄清一些事情:

  1. 我不打算通过 FTP 协议来执行此操作 - 这将作为日常 cron 作业运行
  2. 我的 FTP 站点被用作垃圾场。 人们创建文件夹和子文件夹,这反过来又会填满空间。 大多数东西都被遗弃了。
  3. @Jonathan Leffler 了解我在这里要做什么。 再次,我为造成的混乱道歉。
  4. 我可以发布我的原始 AutoIT 脚本,以显示我正在尝试完成的任务。

编辑 2 - 原始 AutoIT 脚本

#include <array.au3>
#include <Date.au3>
#include <File.au3>
#include <GuiConstants.au3>
#include <GuiButton.au3>
#Include <GuiListBox.au3>
#include <EditConstants.au3>
#include <ListBoxConstants.au3>
#include <WindowsConstants.au3>
#Include <GuiListBox.au3>
#Include <GuiMonthCal.au3>


Global $FolderName = "\\ph-svr-web1\ftpsites"
Global $rootFolder
Global $now = _Date_Time_SystemTimeToDateStr(_Date_Time_GetSystemTime(), 1) 
Global $badSubs = 0, $olderThan = 90
Global $dirsToDeleteListBox, $topIndex, $TotalFoldersFound = 0
Global $ScanFoldersButton, $RemoveFoldersButton, $TotalFoldersFoundLabel, $TotalFoldersFoundNumber
Global $Calendar, $OlderThanNumberDays

Main()

Func Main()
    $MainWindow = GuiCreate("Remove Older Files From FTP Site", 900)
    GUISetFont(12)

    $dirsToDeleteListBox = GUICtrlCreateList("", 40, 35, 550, 300, BitOr($WS_BORDER, $WS_VSCROLL, $LBS_NOTIFY, $LBS_DISABLENOSCROLL, $WS_HSCROLL, $LBS_EXTENDEDSEL))

    $ScanFoldersButton = GuiCtrlCreateButton("Scan FTP Site", 40, 330)
    $RemoveFoldersButton = GUICtrlCreateButton("Delete Selected Folders", 180, 330)
    _GUiCtrlButton_Enable($RemoveFoldersButton, False)

    $TotalFoldersFoundLabel = GUICtrlCreateLabel("Total Folders Found = ", 400, 335)
    $TotalFoldersFoundNumber = GUICtrlCreateLabel($TotalFoldersFound, 560, 335, 100)

    $Calendar = GUICtrlCreateMonthCal($MainWindow, 620, 35, 250, 220);, $MCS_NOTODAY)
    $OlderThanDateLabel = GUICtrlCreateLabel("Searching for files dated prior to:", 630, 270)
    GUISetFont(12, 600)
    $OlderThanDateValue = GUICtrlCreateLabel(SetCalendarDate($olderThan), 650, 300)
    $OlderThanNumberDays = GUICtrlCreateLabel("(" & $olderThan & " days)", 750, 300, 100)
    GUISetFont(12, 400)

    GUISetState()
    GUICtrlSetResizing ($MainWindow, 513 )

    While 1
        $GUIAction = GuiGetMsg()
        Switch $GUIAction
            Case $GUI_EVENT_CLOSE
                ExitLoop ; closes the GUI
            Case $ScanFoldersButton
                _GUICtrlButton_Enable($ScanFoldersButton, False)
                _GUiCtrlButton_Enable($RemoveFoldersButton, False)
                _GUICtrlListBox_ResetContent($dirsToDeleteListBox)
                $TotalFoldersFound = 0
                ScanFolder($FolderName)
                _GUICtrlButton_Enable($ScanFoldersButton, True)
                if $TotalFoldersFound > 0 then
                    _GUiCtrlButton_Enable($RemoveFoldersButton, True)
                    _GUICtrlListBox_SetTopIndex($dirsToDeleteListBox, 0)
                endif
            Case $RemoveFoldersButton
                _GUICtrlButton_Enable($ScanFoldersButton, False)
                _GUiCtrlButton_Enable($RemoveFoldersButton, False)
                RemoveFolders()
                _GUICtrlButton_Enable($ScanFoldersButton, True)
                _GUiCtrlButton_Enable($RemoveFoldersButton, True)
            Case $Calendar
                GUICtrlSetData($OlderThanDateValue, SetCalendarDate(_DateDiff('D', GUICtrlRead($Calendar), $now)))
        endswitch
    wend
EndFunc

Func SetCalendarDate($Days)
    $newDate = _DateAdd('D', -($Days), $now)
    GUICtrlSetData($Calendar, $newDate)
    $olderThan = $Days
    GUICtrlSetData($OlderThanNumberDays, "(" & $olderThan & " days)")
    Return $newDate
EndFunc

Func RemoveFolders()
    $Dirs = _GUICtrlListBox_GetSelItemsText($dirsToDeleteListBox)
    Switch $Dirs[0]
        Case 0
            MsgBox(276,"No folders selected","Please select folders to delete")
        Case Else
            ProgressOn("Deleting FTP Folders...", "Removing")
            $totalDirs = UBound($Dirs) - 1
            for $iI = 1 to $totalDirs
                DirRemove($Dirs[$iI], 1)
                ProgressSet((100 / $totalDirs), $Dirs[$iI])
                $removeFromList = _GUICtrlListBox_FindString($dirsToDeleteListBox, $Dirs[$iI])
                if $removeFromList > 0 then 
                    _GUICtrlListBox_BeginUpdate($dirsToDeleteListBox)
                    _GUICtrlListBox_DeleteString($dirsToDeleteListBox, $removeFromList)
                    _GUICtrlListBox_EndUpdate($dirsToDeleteListBox)
                    $TotalFoldersFound -= 1
                    GUICtrlSetData($TotalFoldersFoundNumber, $TotalFoldersFound)
                endif
            next
            ProgressOff()
            MsgBox(64, "Folders Deleted", "The selected folders have been deleted")
    EndSwitch
EndFunc

Func ScanFolder($SourceFolder)
    Local $Search
    Local $File
    Local $FileAttributes
    Local $FullFilePath
    Local $FileDate

    $Search = FileFindFirstFile($SourceFolder & "\*.*")

    While 1
        If $Search = -1 Then
            ExitLoop
        EndIf

        $File = FileFindNextFile($Search)
        If @error Then ExitLoop

        $FullFilePath = $SourceFolder & ("\" & $File)
        $FileAttributes = FileGetAttrib($FullFilePath)
        $FileDate = _ArrayToString(FileGetTime($FullFilePath), "/", 0, 2)
        $validRoot = ExtractRoot($FullFilePath)


        If StringInStr($FileAttributes,"D") Then
            if $validRoot >= 6 then
            select
                case _DateDiff('D', $FileDate, $now) <= $olderThan
                    $badSubs += 1
                    continuecase
                case StringCompare($rootFolder, $FullFilePath) = 0
                    if $badSubs = 0 then
                        _GUICtrlListBox_BeginUpdate($dirsToDeleteListBox)
                        $topIndex = _GUICtrlListBox_AddString($dirsToDeleteListBox, $rootFolder)
                        _GUICtrlListBox_SetTopIndex($dirsToDeleteListBox, $topIndex)
                        _GUICtrlListBox_EndUpdate($dirsToDeleteListBox)
                        $TotalFoldersFound += 1
                    else
                        $removeFromList = _GUICtrlListBox_FindString($dirsToDeleteListBox, $rootFolder)
                        if $removeFromList >= 0 then 
                            _GUICtrlListBox_BeginUpdate($dirsToDeleteListBox)
                            _GUICtrlListBox_DeleteString($dirsToDeleteListBox, $removeFromList)
                            _GUICtrlListBox_SetTopIndex($dirsToDeleteListBox, $topIndex)
                            _GUICtrlListBox_EndUpdate($dirsToDeleteListBox)
                            $TotalFoldersFound -= 1
                        endif
                        $badSubs = 0
                    endif
            endselect
            GUICtrlSetData($TotalFoldersFoundNumber, $TotalFoldersFound)
            endif
            ScanFolder($FullFilePath)
        EndIf
    Wend

    FileClose($Search)
EndFunc

Func ExtractRoot($FileName)
    $dirArray = StringSplit($FileName, "\")
    if $dirArray[0] >= 6 then
        $rootFolder = _ArrayToString($dirArray, "\", 1, 6)
    endif
    return $dirArray[0]
EndFunc

编辑3:

感谢 Rob,我根据自己的需要修改了他的脚本,如下所示:

#! /bin/bash

if [ -z "$1" ];
then
    echo "You must enter a path after the script name"
    exit
fi

# Usage: "ThisProgram /path/to/root/of/files"

dirs=( $(find "${1}" -maxdepth 1 -type d -print | sed 's:^./::'))
echo "$1"

for dir in "${dirs[@]}"; do

if [ $dir != $1 ]; then
    echo "$dir"
# First, get a list of all subdirs, in depth-first order
find "${dir:-.}" -depth -type d -print0 |
while read -r -d '' i
do

  # For each subdir, test to see if it matches two conditions. If either
  # condition fails, this subdir is not a candidate for deletion.
#  echo "Trying $i"

  #  First: is it at the lowest level, i.e. does it have any surviving children?
  [ "$(find "$i" -type d -print | wc -l)" -gt 1 ] && continue
#  echo "$i has no subdirs"

  # Second: does it have any recent files?
  [ "$(find "$i" -type f -mtime -90 | wc -l)" -gt 0 ] && continue
#  echo "$i has no new files"

  # If we got here, then this candidate has no subdirs and no recent files. Nuke it.
#  echo rm -rf "$i"
  echo "$i"
#  rm -rf "$i"
done

fi
#! /bin/bash

# Usage: "ThisProgram /path/to/root/of/files"
# If "/path/to/root/of/files" is not specified, use the current directory instead.

# First, get a list of all subdirs, in depth-first order
find "${1:-.}" -depth -type d -print0 |
while read -r -d '' i 
do

  # For each subdir, test to see if it matches two conditions. If either
  # condition fails, this subdir is not a candidate for deletion.
  echo "Trying $i"

  #  First: is it at the lowest level, i.e. does it have any surviving children?
  [ "$(find "$i" -type d -print | wc -l)" -gt 1 ] && continue
  echo "$i has no subdirs"

  # Second: does it have any recent files?
  [ "$(find "$i" -type f -mtime -90 | wc -l)" -gt 0 ] && continue
  echo "$i has no new files"

  # If we got here, then this candidate has no subdirs and no recent files. Nuke it.
  echo rm -rf "$i"

done

这里find /ftpdir/Site1/ -type f -mtime +90 -delete你想要的答案: 在这里find /ftpdir/Site1/ -type f -mtime +90 -delete find /ftpdir/Site1/ -type d -empty -mtime +90 -delete

您编写问题的方式对于删除旧文件来说听起来很复杂。

如果您只想删除超过 90 天的文件:

find $DIR -type f -mtime +90d | xargs rm -f

如果您想在该目录中的所有文件都存在 90 天的情况下删除整个目录:

if test $(find $DIR -type f -mtime -90d | wc -l) -eq 0; then
  rm -rf $DIR
fi

如果您想要不同的东西,请澄清您的问题:-)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM