Hi Folks,

I'm a noob but I'm slowly getting addicted to python.
I've been hitting a wall for about 4 hours trying various things to no avail.

It looks to me like it should work and runs without error but....
I expect the blockcount counter to be high (but it's 1)
I expect the accountmatchcounter to be low but it's 131
(looks like they are wrongly placed from the results but I can't see the error in the logic.)

Hopefully one of you chaps will be able to have a giggle and set me straight in one minute.

(any more elegant examples of how to achieve the same results welcomed!)


At the bottom of the code is a sample of the (start of the) original input file I'm working with
it's the output from a wee utility called ntfsdump - the files are around 1.5mb in size
ideally I'd be using python to parse the directory structure reporting on the account anomalies but I'm a noob at python, can't install it on the servers and I'm too afraid to wrap an exe with py2exe and run this on a production server.

# Setup array of school accounts used in perms(only the ones we worry about if they're not there)
listofaccounts = ["spgstaff", "spgxstaff", "spmstaff"]

# setup log file
#log001=open("c:\log001.txt", "a")  (for use at work)
log001=open("/home/scobie/Desktop/log001.txt", "a")

# open input file - first bit is tkinter gui and the last line deals with the file opening
import Tkinter
from tkFileDialog import askopenfilename
root = Tkinter.Tk()
root.withdraw() # hide the main GUI window for our example
nmapresultsfile = askopenfilename()


#################################################
### this codeblock from someone else --->
#################################################
#strip off the leading info - top 5 lines - save as nmaptrimmed for further operations below
tempFile = open(nmapresultsfile)
tempList = []
for lineNum, line in enumerate(tempFile):
        if lineNum >= 0 and lineNum < 5:
             continue  # do next lineNum, line without append()
        tempList.append(line)
tempFile.close()
#tempFile = open("c:\nmaptrimmed.txt", 'w')   (for use at work)
tempFile = open("/home/scobie/Desktop/nmaptrimmed.txt", 'w')
tempFile.writelines(tempList)
tempFile.close()
#################################################
### <--- this codeblock from someone else
#################################################

###
# perform checks on each block in inputfile (blocks split with one empty line) incrementing blockcount as they are processed
# iterate over each line in block to check for the existence of any of the accounts in listofaccounts
# for each match add 1 to accountmatchcounter and if this is = 0 then add block number to logfile.
###
#inputfilename = open("c:\nmaptrimmed.txt", "r")
inputfilename = open("/home/scobie/Desktop/nmaptrimmed.txt", "r")
blockcount = 1  # set to increment when there's a blank line
accountmatchcounter = 1   # set to increment within each block iteration where there's a regex match

for line in inputfilename:
        if line[0:1]=="c":
                for item in listofaccounts:
                        if line.find(item)!=-1:
                                accountmatchcounter = accountmatchcounter + 1
                        else:
                                pass
                        
        elif accountmatchcounter == 0:
                log001.writelines("possible problem - no account set in block " + repr(blockcount) + "\n")
                blockcount = blockcount + 1
                accountmatchcounter = 0                
        else:
                pass

#################################################
#################################################

log001.close()
inputfilename.close()



#below is an example of the input file (it's just the start - it's around 1.5mb)

#23/09/2010 13:21 - Somarsoft DumpSec (formerly DumpAcl) - \\IT85112 (local)
#Path (exception dirs and files),Account                     ,Own ,Dir        File       ,Success    Failure    ,
#
#c:\shares\staffresources\
#
#c:\shares\staffresources\,SPGAS01\Administrators 
#c:\shares\staffresources\,SCHOOLS\delpaisleygrammar 
#c:\shares\staffresources\,SCHOOLS\Domain Admins 
#c:\shares\staffresources\,SCHOOLS\edcorpusers     
#c:\shares\staffresources\,SCHOOLS\spgstaff 
#
#c:\shares\staffresources\art\,SPGAS01\Administrators 
#c:\shares\staffresources\art\,SCHOOLS\spgart                                
#c:\shares\staffresources\art\,SCHOOLS\pgsartq        
#
#c:\shares\staffresources\art\02Ali Boss.xlsx,SPGAS01\Administrators 
#c:\shares\staffresources\art\02Ali Boss.xlsx,SCHOOLS\spgart
#c:\shares\staffresources\art\02Ali Boss.xlsx,SCHOOLS\spgpowerstaff  
#c:\shares\staffresources\art\02Ali Boss.xlsx,SCHOOLS\spgxstaff    
#c:\shares\staffresources\art\02Ali Boss.xlsx,SCHOOLS\spgjohnsa1

Dani AI

Generated

Quick diagnosis and what went wrong
The two practical bugs in the original loop were (1) accountmatchcounter was initialized to 1 instead of 0, so the "no-match" condition could never be reached, and (2) block counting/reset happened in the wrong branch — the code increments block numbers only when a non-c: line is seen and accountmatchcounter == 0, which both prevents correct block numbering and never resets the per-block state reliably. correctly pointed out the initialization problem; the other issue is the per-line branching logic that mixes "within a block" checks with "end of block" actions. Using line.startswith('c:') is also brittle if lines have leading whitespace or different case.

A simpler, robust approach
Trim the header, split the file into logical blocks (split on one-or-more blank lines), then examine each block as a whole: if the block contains a path line (a line beginning with c:) and none of the account names appear anywhere in that block, log the block number. Use a compiled regular expression with word boundaries or a set membership check for exact matches, and prefer with open(...) for files so handles are closed cleanly.

Example implementation (different approach than earlier replies)

import re

accounts = ['spgstaff','spgxstaff','spmstaff']
acct_re = re.compile(r'\b(?:' + '|'.join(map(re.escape, accounts)) + r')\b', re.I)

with open('nmaptrimmed.txt') as f:
    text = ''.join(f.readlines()[5:])        # drop header lines

blocks = re.split(r'\n\s*\n', text)          # split on blank-line separators
bad_blocks = []

for i, block in enumerate(blocks, 1):
    if any(line.strip().lower().startswith('c:') for line in block.splitlines()):
        if not acct_re.search(block):
            bad_blocks.append(i)

with open('log001.txt', 'a') as log:
    for b in bad_blocks:
        log.write('possible problem - no account set in block {}\n'.format(b))

Notes and troubleshooting
Make regex case-insensitive (re.I) or normalize to .lower(). Use re.escape() when building patterns from variable account names. For very large files, streaming and incremental block-building is preferable to loading the whole file into memory. This pattern yields clear block numbers and avoids the off-by-one / branch-placement errors seen in the original loop. ’s sample data and ’s fix illustrate the same principles; this version focuses on block-level logic and exact matching.

Recommended Answers

All 4 Replies

Sorry - forgot to mention

it's just the "for line in inputfile" section that's confusing me

the line strip, tkinter block and fileopen/write/appends all seem ok

(I should have just put that piece of code in - sorry!)


thanks,

Scott

Line 44 sets variable to 1 and it will be incremented, that will only be made zero if it is allready zero (test in line 54, assignment line 57.

Would this be what you are after little cleaner and closer to your comment?

import Tkinter
from tkFileDialog import askopenfilename
root = Tkinter.Tk()
root.withdraw() # hide the main GUI window for our example

# Setup array of school accounts used in perms(only the ones we worry about if they're not there)
listofaccounts = ["spgstaff", "spgxstaff", "spmstaff"]

# setup log file
with open("log001.txt", "a") as log001:

    # perform checks on each block in inputfile (blocks split with one empty line)
    # incrementing blockcount as they are processed
    blockcount = 1  # set to increment when there's a blank line

    with open(askopenfilename()) as inputfile:
        #strip off the leading info - top 5 lines
        for drop in range(5):
            inputfile.readline()

        for line in inputfile:
            # allow other than c drive
            #if  len(line) > 2 and line[1] == ":":
            # only c:
            if line.startswith('c:'):
                # iterate over each line in block to check for the existence of any of the accounts in listofaccounts
                if not any(item in line for item in listofaccounts):
                    # print '%i: Bad: %s' % (blockcount,line), # debug
                    log001.writelines("possible problem - no account set in block %r\n" % blockcount)
            else:
                 blockcount = blockcount + 1
                 # print # debug

print '''

Blockcount %i''' % blockcount

I can't believe I didn't see that .... well it's certainly one schoolboy error I hope I don't make again!!

thanks for your quick response Tonyjv

that's beautiful code - I look forward to examining in more detail and hopefully absorbing some of the nicer ways to do things wrt python.

You are wellcome. Can not avoid seeing the similarity of your comment, line 26, and actual my code line 27.

Quite a small program only 20 lines without comments and empty lines:

>>> len(list(line for line in open('blockcheck.py')
     if line.strip() and not line.strip().startswith('#')))
20
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.