#!/usr/local/bin/python # csh2sh.py - convert csh scripts to sh script. # The input filename should be in the form # x.csh, and the output file will be x.sh # # WARNING: This script only does some very crude # substitutions. Code generated by this script # should be considered as a starting point for # manual translation to sh. # Version 11/15/09 # Synopsis: # csh2sh.py infile # infile - csh script import sys import os import string import re import shutil # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - class Parameters : "Wrapper class for command line parameters" def __init__(self) : self.IFN = "" self.OFN = "" # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - def READARGS(P) : "Read command line arguments into a Parameter object" "Right now, only IFN is supported." NUMARGS = len(sys.argv) if NUMARGS >= 1 : P.IFN = sys.argv[1] P.OFN = P.IFN if P.OFN.endswith('.csh') : P.OFN = P.OFN[0:-4] P.OFN = P.OFN + '.sh' # I = 2 # while (I < NUMARGS) : # # This code is here as a placeholder for # # future command line switches # if sys.argv[I] == "-dummy1" : # I = I + 1 # if I < NUMARGS : # I = I + 1 # elif sys.argv[I] == "-dummy2" : # I = I + 1 # if I < NUMARGS : # I = I + 1 # else : # P.OFN = sys.argv[I] # I = NUMARGS return # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - class scriptfile : "Contents of the file" def __init__(self) : self.text = "" def readFile(self,IFN) : INFILE = open(IFN,'r') self.text = INFILE.read() INFILE.close() return def writeFile(self,OFN) : OUTFILE = open(OFN,'w') OUTFILE.write(self.text) OUTFILE.close() return # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - def CONVERT(SCRIPT) : "Iterate through the script replacing csh syntax with" "sh syntax." SCRIPT.text = re.sub('#!/bin/csh','#!/bin/sh',SCRIPT.text) # arguments SCRIPT.text = re.sub('\$#argv','$#',SCRIPT.text) SCRIPT.text = re.sub('\$argv','$*',SCRIPT.text) # We still need to handle the usage: $argv[n] # Convert $home, $path to $HOME, $PATH SCRIPT.text = re.sub('\$home','$HOME',SCRIPT.text) SCRIPT.text = re.sub('\$path','$PATH',SCRIPT.text) #------ File name manipulations ----------- # Basename: $FILE:t EXP1='(\$)(.+)(:t)' EXP2='`basename \g<1>\g<2>`' SCRIPT.text = re.sub(EXP1,EXP2,SCRIPT.text) # File extension: $FILE:e EXP1='(\$)(.+)(:e)' EXP2='\g<1>{\g<2>##*.}' SCRIPT.text = re.sub(EXP1,EXP2,SCRIPT.text) # Filename minus file extension: $FILE:r EXP1='(\$)(.+)(:r)' EXP2='\g<1>{\g<2>%.*}' SCRIPT.text = re.sub(EXP1,EXP2,SCRIPT.text) # ---------- Flow of control statements --------------------- # if then EXP1='([\t ]*)(if[\t ]+)(.+)([\t ]+then)' EXP2='\g<1>if [ \g<3> ]\n\g<1>\tthen' SCRIPT.text = re.sub(EXP1,EXP2,SCRIPT.text) EXP1='(if \[)([\t ]+)(\()(.*)(\))([\t ]*)(\])' EXP2='if [ \g<4> ]' SCRIPT.text = re.sub(EXP1,EXP2,SCRIPT.text) SCRIPT.text = re.sub('endif','fi',SCRIPT.text) # set, setenv EXP1 = '(set[\t ]+)(\S+)([\t ]+=[\t ]+)(\()(\s)(.*)(\s)(\))' EXP2 = '\g<1>\g<2>\g<3>"\g<6>"' SCRIPT.text = re.sub(EXP1,EXP2,SCRIPT.text) SCRIPT.text = re.sub('(set[\t ]+)(\S+)([\t ]+=[\t ]+)','\g<2>=',SCRIPT.text) SCRIPT.text = re.sub('([\t ]*)(setenv[\t ]+)(\S+)([\t ]+)(\S+)','\g<1>\g<3>=\g<5>\n\g<1>export \g<3>',SCRIPT.text) # switch SCRIPT.text = re.sub('(switch[\t ]+\()(\S+)([\t ]*\)[\t ]*)','case \g<2> in',SCRIPT.text) SCRIPT.text = re.sub('(case[\t ]+)(\S+)([\t ]*\:[\t ]*)','\g<2>)',SCRIPT.text) SCRIPT.text = re.sub('breaksw',';;',SCRIPT.text) SCRIPT.text = re.sub('default:','*)',SCRIPT.text) SCRIPT.text = re.sub('endsw','esac',SCRIPT.text) # while EXP1 = '(while[\t ]+)(\()(.*)(\)[\t ]*\n)' EXP2 = 'while [ \g<3> ]\n\tdo\n' SCRIPT.text = re.sub(EXP1,EXP2,SCRIPT.text) SCRIPT.text = re.sub('(\n[\t ]*)(end)','\g<1>done',SCRIPT.text) # foreach #this doesn't seem to work and I can't figure out why. EXP1 = '([\t ]*)(foreach[\t ]+)(\S+)([\t ]+)(.*)' EXP2 = '\g<1>for \g<3> in \g<5>\n\g<1> do\n' SCRIPT.text = re.sub(EXP1,EXP2,SCRIPT.text) # Also replace parentheses with double quotes, for lists in a for expression EXP1 = '(for[\t ]+\S+[\t ]+in[\t ])(\()(.*)(\))' EXP2 = '\g<1>"\g<3>"' SCRIPT.text = re.sub(EXP1,EXP2,SCRIPT.text) #Lists EXP1 = re.compile('(\S+=)(\()(.*?)(\))',re.DOTALL |re.MULTILINE) EXP2 = '\g<1>"\g<3>"' SCRIPT.text = re.sub(EXP1,EXP2,SCRIPT.text,re.DOTALL |re.MULTILINE) # boolean tests EXP1 = '(\$\{\?)(\S+)(\})' EXP2 = '! -z "$\g<2>"' SCRIPT.text = re.sub(EXP1,EXP2,SCRIPT.text) return #======================== MAIN PROCEDURE ========================== P = Parameters () READARGS(P) # Read the csh file SCRIPT = scriptfile() SCRIPT.readFile(P.IFN) # Replace csh syntax with sh syntax. CONVERT(SCRIPT) # WARNING: this is currently a very simple-minded replacement. SCRIPT.writeFile(P.OFN) os.chmod(P.OFN,0755)