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
inc_hour
if [ $i -gt $1 ]; then
echo "files$year$month$day$hour"
fi
done
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
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
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] ) ):
print "files" + strftime( fmt, localtime( secs + 10 + i*21599.9999 ) )
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
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.
vBulletin® v3.8.8, Copyright ©2000-2024, vBulletin Solutions, Inc.