在bash中解析文件夹名称

时间:2010-10-07 00:57:59

标签: linux bash grep

我有使用命名约定的文件夹:

yearmonthday_jobcode_descriptor

即20101007_GR1234_Whatsit

我正在尝试编写一个执行以下操作的脚本:

  • 将日期早于$ X的任何文件夹移动到./old
  • 移动日期为将来的所有文件夹./old
  • 移动任何不符合约定的文件夹./old
  • 删除日期早于$ X + $ Y
  • 的./old中的所有文件夹

这是我当前的循环,因为你可以看到我的bash脚本非常平庸。

#!/bin/bash

for file in $1/*; do
   if [ -d $file ]; then
        echo $(echo $file | grep -oE "[0-9]{8}_[A-Z]*[0-9]*_?.*")
   fi
done

我可以处理所有循环,目前我主要关心的是如何将文件夹名称提取到可以比较日期的变量中。上面的当前正则表达式只是检查是否符合约定。

4 个答案:

答案 0 :(得分:4)

您可以使用cut命令来标记字符串(-d指定分隔符,-f指定要保留的字段) -

echo 20101007_GR1234_Whatsit | cut -d'_' -f1

给出

20101007

从那里,您可以使用date命令来解析日期 -

foo=`date -d 20101007 +%s`

会将日期字符串转换为纪元时间(自1970年1月1日起的秒数),然后可以轻松比较。

如果你不想搞乱纪元时间,你可以多次调用日期来解析不同的部分 -

 day=`date -d 20101007 +%d`
 month=`date -d 20101007 +%m`
 year=`date -d 20101007 +%Y`

但它会使你的比较更加复杂。

答案 1 :(得分:2)

$ foo="20101007_GR1234_Whatsit"
$ echo ${foo%%_*}
20101007

答案 2 :(得分:1)

#!/bin/bash


ls -d ????????_[A-Z][A-Z]*_* | awk 'BEGIN{
  x=mktime("2010 10 08 00 00 00") # set your X here, whatever it is
  y=mktime("2010 10 02 00 00 00") # set your Y here, whatever it is
  olddir="/tmp/old"
}
{
   yr=substr($0,1,4) # get year
   mth=substr($0,5,2) # get month
   day=substr($0,7,2) # get day
   t= mktime(yr" "mth" "day" 00 00 00")  #convert to secs for comparison
   if (t < 0) { print "Wrong format: "$0 ;next}
   if ( t > x){
      print $0 " is later than X: "x
   }else{
      print "moving "$0" to old"
      cmd="mv $0 "oldir
      print cmd
      #system(cmd) #uncomment to do actual moving
   }
   if ( t> (x+y) ){
        ..............
   }
}'

答案 3 :(得分:1)

这是我的最终解决方案,适用于将来尝试这样做的任何人:

#!/bin/bash

ARCHIVE="old"
NOW=`date +%s`
GRACE_PERIOD=$((60*60*24*7*2))
CUTOFF=$(($NOW-$GRACE_PERIOD))
DEADLINE=$(($CUTOFF-$GRACE_PERIOD))

function getos {
    UNAME=`uname`
    PLATFORM="unknown"

    if [[ "$UNAME" == 'Linux' ]]; then
        echo 'linux'
    elif [[ "$UNAME" == 'Darwin' ]]; then
        echo 'osx'
    else
        echo 'linux'
    fi
}

function dateToTimestamp {
    DATE="$1"
    OS=`getos`
    TIMESTAMP='empty'

    if [[ "$OS" == 'linux' ]]; then
        TIMESTAMP=`date -d $DATE +%s`
    elif [[ "$OS" == 'osx' ]]; then
        TIMESTAMP=`date -j -f "%Y%m%d" "$DATE" "+%s"`
    fi

    echo $TIMESTAMP
}

function movetoarchive {
    ITEM="$1"
    if [ ! -d "$ARCHIVE" ]; then
        mkdir $ARCHIVE
    fi

    FOLDER=`date +"%Y%m%d"`

    if [ ! -d "$ARCHIVE/$FOLDER" ]; then
        mkdir $ARCHIVE/$FOLDER
    fi

    mv $ITEM $ARCHIVE/$FOLDER/$ITEM
}

function deletefromarchive {
    ITEM="$1"
    WD=`pwd`

    MATCH=$(echo $WD | grep -oE ".*?/$WORKING_DIR/$ARCHIVE$")
    if [ -n "$MATCH" ]; then
        rm -rf $ITEM;
    fi
}

WORKING_DIR="$1";

cd "$WORKING_DIR"

for file in *; do
    if [ -d $file ]; then
        if [ "$file" != "$ARCHIVE" ]; then
            MATCH=$(echo $file | grep -oE "[0-9]{8}-[A-Z]*[0-9]*-?.*")
            if [ -z "$MATCH" ]; then
                movetoarchive $file
            else
                DATE=$(echo $file | cut -d'-' -f1);
                TIMESTAMP=`dateToTimestamp $DATE`
                if [[ "$TIMESTAMP" > "$NOW" ]]; then
                    movetoarchive $file
                elif [[ "$TIMESTAMP" < "$CUTOFF" ]]; then
                    movetoarchive $file
                fi
            fi
        fi
       fi
done

cd $ARCHIVE

for file in *; do
    if [ -d $file ]; then
        MATCH=$(echo $file | grep -oE "^[0-9]{8}$")
        if [ -z "$MATCH" ]; then
            deletefromarchive $file
        else
            TIMESTAMP=`dateToTimestamp $file`
            if [[ "$TIMESTAMP" > "$NOW" ]]; then
                deletefromarchive $file
            elif [[ "$TIMESTAMP" < "$DEADLINE" ]]; then
                deletefromarchive $file
            fi
        fi
    fi
done