2011-09-02 123 views
0

我正在寻找创建一个bash脚本,递归地通过目录,并从最后的树开始,按日期检查文件。如果最新的文件大于90天,请上传一个目录并检查相同的内容。如果没有比90天更新的文件,请删除根目录。bash脚本根据修改的文件日期删除目录

例如

/ftpdir /站点1/folder1中/文件夹2

如果文件夹2不具有较新的文件,但文件夹1确实除去夹之一,但保持站点1

我已经写过这个AutoIT,但现在需要它作为bash脚本,我有点失落。

感谢

编辑:我想我是清楚的,但让我澄清一些事情:

  1. 我不是在寻找通过FTP协议来做到这一点 - 这将运行作为每日cron工作
  2. 我的FTP站点被用作垃圾场。人们创建文件夹和子文件夹,这反过来填补了空间。大部分东西都被抛弃了。
  3. @Jonathan Leffler了解我在这里要做什么。再次,我对这种混乱表示歉意。
  4. 我可以发布我的原始AutoIT脚本,显示我正在尝试完成。

EDIT 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 
+3

什么问题?这没有多大意义。如果其最新文件大于90天并且其父目录也没有比90天更新的文件,则删除目录:S为什么?明确你想要做什么。如果folder1有两个subdirs会发生什么?删除目录的条件是什么? – c00kiemon5ter

+0

把它想象成一个包含关于“事件”的保存电子邮件的目录,每个电子邮件包含一个文件。如果最近的消息已超过90天,则事件结束并结束,并且可以删除整个目录。如果任何消息少于90天,请将所有文件保存在目录中;事件仍然“活跃”,我们需要所有的信息。该示例使用FTP。它仍然令人困惑地描述。 –

+0

原始问题中的编辑 –

回答

2
#! /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 
+0

周二我回到办公室时我会试试这个。 –

+0

这似乎工作,但我将如何解决空白问题? –

+1

我已将脚本更新为空白。请注意,脚本现在需要bash。 –

0

你写你的问题的方式听起来很复杂,只是删除旧文件。

如果你想只删除超过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 

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

+0

这样做的问题是,即使目录中有年龄较小的文件,它也会删除年龄大于90天的文件,这并不是问题所要求的(如果我理解正确;我可能会感到困惑,因为它不是全部那写得很清楚)。 –

+0

原始问题编辑 –