2009-10-27 52 views
9

我試圖創建一個腳本,它將通過文件以下列格式寫入文件:yyyymmdd.hh.filename。在兩個給定的日期之間的bash循環

該腳本調用:

./loopscript.sh 20091026.00 23 
./loopscript.sh 20091026.11 15 
./loopscript.sh 20091026.09 20091027.17 

需要的是對腳本來檢查這兩個指定的日期/小時之間的每個小時。

例如

cat 20091026.00.filename |more 
cat 20091026.01.filename |more 
... 
cat 20091026.23.filename |more 
cat 20091027.01.filename |more 
cat 20091027.02.filename |more 
... 

等等。

任何想法該怎麼辦?我對標準的0 - x循環沒有任何困難。或簡單的循環。只是不知道如何去上述。

+0

無用的'cat':只使用'更多文件名' – 2009-10-27 09:43:08

回答

5

要處理兩個給定日期/小時之間的每個文件,可以使用以下命令:

#!/usr/bin/bash 
#set -x 

usage() { 
    echo 'Usage: loopscript.sh <from> <to>' 
    echo '  <from> MUST be yyyymmdd.hh or empty, meaning 00000000.00' 
    echo '  <to> can be shorter and is affected by <from>' 
    echo '   e.g., 20091026.00  27.01 becomes' 
    echo '    20091026.00 20091027.01' 
    echo '   If empty, it is set to 99999999.99' 
    echo 'Arguments were:' 
    echo " '${from}'" 
    echo " '${to}'" 
} 

# Check parameters. 

from="00000000.00" 
to="99999999.99" 
if [[ ! -z "$1" ]] ; then 
    from=$1 
fi 
if [[ ! -z "$2" ]] ; then 
    to=$2 
fi 
## Insert this to default to rest-of-day when first argument 
## but no second argument. Basically just sets second 
## argument to 23 so it will be transformed to end-of-day. 
#if [[ ! -z "$1"]] ; then 
# if [[ -z "$2"]] ; then 
#  to=23 
# fi 
#fi 

if [[ ${#from} -ne 11 || ${#to} -gt 11 ]] ; then 
    usage 
    exit 1 
fi 

# Sneaky code to modify a short "to" based on the start of "from". 
# ${#from} is the length of ${from}. 
# $((${#from}-${#to})) is the length difference between ${from} and ${to} 
# ${from:0:$((${#from}-${#to}))} is the start of ${from} long enough 
# to make ${to} the same length. 
# ${from:0:$((${#from}-${#to}))}${to} is that with ${to} appended. 
# Voila! Easy, no? 

if [[ ${#to} -lt ${#from} ]] ; then 
    to=${from:0:$((${#from}-${#to}))}${to} 
fi 

# Process all files, checking that they're inside the range. 

echo "From ${from} to ${to}" 
for file in [0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9].[0-9][0-9].* ; do 
    if [[ ! (${file:0:11} < ${from} || ${file:0:11} > ${to}) ]] ; then 
     echo " ${file}" 
    fi 
done 

當您創建的文件20091026.00.${RANDOM}通過20091028.23.${RANDOM}包括,這是一對樣品運行:

pax> ./loopscript.sh 20091026.07 9 
From 20091026.07 to 20091026.09 
    20091026.07.21772 
    20091026.08.31390 
    20091026.09.9214 
pax> ./loopscript.sh 20091027.21 28.02 
From 20091027.21 to 20091028.02 
    20091027.21.22582 
    20091027.22.30063 
    20091027.23.29437 
    20091028.00.14744 
    20091028.01.6827 
    20091028.02.10366 
pax> ./loopscript.sh 00000000.00 99999999.99 # or just leave off the parameters. 
    20091026.00.25772 
    20091026.01.25964 
    20091026.02.21132 
    20091026.03.3116 
    20091026.04.6271 
    20091026.05.14870 
    20091026.06.28826 
    : : : 
    20091028.17.20089 
    20091028.18.13816 
    20091028.19.7650 
    20091028.20.20927 
    20091028.21.13248 
    20091028.22.9125 
    20091028.23.7870 

正如你所看到的,第一個參數必須是正確的格式yyyymmdd.hh。第二個參數可以更短,因爲它繼承了第一個參數的開始,使其成爲正確的長度。

這隻會嘗試處理存在(從ls)和正確格式的文件,而不是每個日期/小時範圍內的文件。如果你有稀疏文件(包括範圍的開始和結尾),這將更有效率,因爲它不需要檢查文件是否存在。

順便說一句,這是創建的測試文件的命令,如果你有興趣:

pax> for dt in 20091026 20091027 20091028 ; do 
     for tm in 00 01 02 ... you get the idea ... 21 22 23 ; do 
      touch $dt.$tm.$RANDOM 
     done 
    done 

請不要輸入,在逐字,然後抱怨說,它創建的文件,如:

20091026.you.12345 
20091028.idea.77 

我只修剪了這條線,所以它適合代碼寬度。 :-)

+0

哇,我被這個答案吹走了。我會回到你們家。 – Chasester 2009-10-27 08:25:00

+0

如果有人輸入./loopscript.sh 20091026.07沒有值。它會從20091026.07運行到20091023.07有沒有辦法將它默認爲.23?我有這個代碼的最上面部分 - 將當前日期設置爲=「$(date +%Y)$(date +%m)$(date +%d)」的st/end時間 「 .00「 to =」$(date +%Y)$(date +%m)$(date +%d)「。23」 if [[! -z「$ 2」]];然後 from = $ 2 fi if [[! -z「$ 3」]];那麼 到= $ 3 fi if [[$ {#from} -ne 11 || $ {#to} -gt 11]];然後 用法 出口1 fi if [[$ {#to} -lt $ {#from}]];然後 to = $ {from:0:$(($ {#from} - $ {#to}))} {{to} fi – Chasester 2009-10-27 10:14:02

+0

而不是前兩個測試,只需對位置參數進行第三個測試直接:'$ {#1}'後跟賦值如'from = {{1:-00000000.00}''。創建測試文件內循環:'for tm in 0 {0..24}; do touch $ dt。$ {tm:-2}。$ RANDOM; done'或沒有內部循環:'touch $ dt.0 {0..9}。$ RANDOM;觸摸$ dt。{10..19}。$ RANDOM;觸摸$ dt。{20..23}。$ RANDOM' – 2009-10-27 10:31:20

1

一種可能的解決方案:將日期轉換爲標準的Unix表示形式,即「從曆元開始經過的秒數」和循環,每次迭代將此數字增加3600(一小時內的秒數)。例如:

#!/bin/bash 

# Parse your input to date and hour first, so you get: 
date_from=20090911 
hour_from=10 
date_to=20091026 
hour_to=01 

i=`date --date="$date_from $hour_from:00:00" +%s` 
j=`date --date="$date_to $hour_to:00:00" +%s` 

while [[ $i < $j ]]; do 
    date -d "1970-01-01 $i sec" "+%Y%m%d.%H" 
    i=$[ $i + 3600 ] 
done 
+0

建議每小時有3600秒 - 並按要求增加小時數。 – 2009-10-27 06:42:47

+0

由於時區的限制,此代碼會產生幾個小時的差異。 – kachar 2012-07-23 11:06:52

23

如何:

#!/bin/bash 

date1=$1 
date2=$2 

#verify dates 
if ! date -d "$date1" 2>&1 > /dev/null ; 
    then echo "first date is invalid" ; exit 1 
fi 
if ! date -d "$date2" 2>&1 > /dev/null ; 
    then echo "second date is invalid" ; exit 1 
fi 

#set current and end date 
current=$(date -d "$date1") 
end=$(date -d "$date2 +1 hours") 

#loop over all dates 
while [ "$end" != "$current" ] 
do 
    file=$(date -d "$current" +%Y%m%d.%H) 
    cat $file."filename" | more 
    current=$(date -d "$current +1 hours") 
done 
+0

這是合理的日期,但不處理小時。其實,對日期也有一定的懷疑 - 如果你給它的參數20091027和20091028,你會從20091027.00到20091028.00獲得 - 我預計它會停在1027.23或1028.23。 – paxdiablo 2009-10-27 07:26:58

+0

如果您以「20091027 00」「20091028 03」來稱呼它,它會處理幾小時,忘記提及這一點。 – Puppe 2009-10-27 07:36:09

+0

艾啊,那好點。據推測,這是做日常工作的日期。不錯。 – paxdiablo 2009-10-27 07:41:29

相關問題