PDA

View Full Version : Unix Programming 101...question inside


t_hah
Aug 11, 2003, 12:48 PM
I really need to learn how to program under Unix, so this is my first real effort to do so.

I have two directory with lot of files in it. I need to run some script on each file in one directory and output the files with a different extension to the second directory . Let's just call the script 'script_01'.
The files are numbered according to date. They go like this: 03010100, which would correspond to January 01, 2003. There are four different number endings, 00, 06, 12, 18. They correspond to time of the day.

So I need to write a script, preferrably in kcsh that will take an input starting and ending file name and run script_01 on all the file between the input parameters.

Let's assume that script_01 is located in: /user/~test/scripts/
script_01 has two input arguments an input file and the output file.
The two directories with the file are located at:
/user/~testA/files1
/user/~testB/files2
I think it would be easier to write the script so that it would be run from:
/user/~test/


Thank you for your help,

t

Arkham_c
Aug 11, 2003, 03:54 PM
Originally posted by t_hah:
I really need to learn how to program under Unix, so this is my first real effort to do so.

I have two directory with lot of files in it. I need to run some script on each file in one directory and output the files with a different extension to the second directory . Let's just call the script 'script_01'.
The files are numbered according to date. They go like this: 03010100, which would correspond to January 01, 2003. There are four different number endings, 00, 06, 12, 18. They correspond to time of the day.

So I need to write a script, preferrably in kcsh that will take an input starting and ending file name and run script_01 on all the file between the input parameters.

Let's assume that script_01 is located in: /user/~test/scripts/
script_01 has two input arguments an input file and the output file.
The two directories with the file are located at:
/user/~testA/files1
/user/~testB/files2
I think it would be easier to write the script so that it would be run from:
/user/~test/


Thank you for your help,

t

First, there's no such thing as kcsh. There is ksh, csh, and tcsh. ksh would be ok for writing a shell script, since it's a bourne shell derivative, but you should never write a script in csh or tcsh. For reasons why, look here:

http://www.faqs.org/faqs/unix-faq/shell/csh-whynot/

With that aside, I recommend writing shell scripts to run under standard /bin/sh so as to be portable across systems.

Now on to your specific question. You have an input directory, and output directory, and some files in the input directory.

You want to choose files based on filenames within a date range (and the dates are encoded in the filename), and do what with them? Copy them to the output directory? Rename them? Process them in some way? Be specific and we'll try to help.

PS. I'll tell you right now you can do this in a shell script, but it would be cleaner if you used perl or python.

Gary Kerbaugh
Aug 12, 2003, 03:18 PM
   As Arkham_c points out, this is what Perl's Date::Parse module is for but if you want a raw solution in bash, you can use the following sh functions. Repeated calls to the inc_hour function will actually increment the year, month day and hour varibles so that when concatenated they will match the sequence of numbers appended to your file names. I've included the loop I used to test it, to give you an idea of usage but I haven't any idea what you really want to do with the files.

script
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#!/bin/sh

year=00
month=01
day=01
hour=00
max_days=( 31 28 31 30 31 30 31 31 30 31 30 31 )

function inc_year
{
  year=${year#0}
  if [ "$year" -lt "9" ]; then
    let "year += 1"
    year="0"$year
  else
    let "year += 1"
  fi
}

function inc_month
{
  month=${month#0}
  if [ "$month" -eq "12" ]; then
    inc_year
    month=01
  elif [ "$month" -lt "9" ]; then
    let "month += 1"
    month="0"$month
  else
    let "month += 1"
  fi
}

function inc_day
{
  day=${day#0}
  let "tmp_month = ${month#0} - 1"
  if [ "$day" -eq "${max_days[tmp_month]}" ]; then
    inc_month
    day=01
  elif [ "$day" -lt "9" ]; then
    let "day += 1"
    day="0"$day
  else
    let "day += 1"
  fi
}

function inc_hour
{
  if [ "$hour" -eq "18" ]; then
    inc_day
    hour=00
  elif [ "$hour" -eq "00" ]; then
    hour="06"
  else
    let "hour += 6"
  fi
}

for (( i=0; i < $2; i++ )); do
&nbsp;&nbsp;inc_hour
&nbsp;&nbsp;if [ $i -gt $1 ]; then
&nbsp;&nbsp;&nbsp;&nbsp;echo "files$year$month$day$hour"
&nbsp;&nbsp;fi
done
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
&nbsp;&nbsp;&nbsp;Even if this proves useful, it also shows the potential value in powerful tools like those available in Perl or Python.

Gary Kerbaugh
Aug 12, 2003, 08:24 PM
&nbsp;&nbsp;&nbsp;Just to make my point a little more strongly, here's a python script that makes a similar list of filenames but the arguments are a little different. The first is the number of 6 hour blocks after 00010100 at which to start and the second the number of filenames to produce. Here's the script:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#!/usr/bin/python

from sys import argv
from time import localtime, mktime, strptime, strftime

fmt = "%y%m%d%H"
secs = mktime(strptime("00010100",fmt))
for i in range( int( argv[1] ), int( argv[1] ) + int( argv[2] ) ):
&nbsp;&nbsp;print "files" + strftime( fmt, localtime( secs + 10 + i*21599.9999 ) )
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
&nbsp;&nbsp;&nbsp;The point of course is that this is a little shorter than the previous. If sh has such date formating capabilities, (other than for the current date) I apologize for being unaware of them.