<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">thanks for the responses.   i'm having quite a good time learning python.</div><div class="gmail_quote"><br></div><div class="gmail_quote">On Thu, Sep 18, 2014 at 11:45 AM, Chris Kaynor <span dir="ltr"><<a href="mailto:ckaynor@zindagigames.com" target="_blank">ckaynor@zindagigames.com</a>></span> wrote: <blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><div></div><div>Additionally, you may want to specify binary mode by using open(file_path, 'rb') to ensure platform-independence ('r' uses Universal newlines, which means on Windows, Python will convert "\r\n" to "\n" while reading the file). Additionally, some platforms will treat binary files differently.</div></div></div></div></blockquote><div><br></div><div>would it be good to use 'rb' all the time?</div></div></div><div class="gmail_extra"><br></div><div class="gmail_extra">On Thu, Sep 18, 2014 at 11:48 AM, Chris Angelico <span dir="ltr"><<a href="mailto:rosuav@gmail.com" target="_blank">rosuav@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><span class="">On Fri, Sep 19, 2014 at 4:11 AM, David Alban <<a href="mailto:extasia@extasia.org">extasia@extasia.org</a>> wrote:</span><br>> exit( 0 )<br><br>Unnecessary - if you omit this, you'll exit 0 implicitly at the end of<br>the script.<br></blockquote><div><br></div><div>aha.  i've been doing this for years even with perl, and apparently it's not necessary in perl either.  i was influenced by shell.</div><div><br></div><div>this shell code:</div><div><br></div><div><font face="courier new, monospace"><b>     if [[ -n $report_mode ]] ; then</b></font></div><div><font face="courier new, monospace"><b>        do_report</b></font></div><div><font face="courier new, monospace"><b>     fi</b></font></div><div><font face="courier new, monospace"><b><br></b></font></div><div><font face="courier new, monospace"><b>     exit 0</b></font></div><div><br></div><div>is an example of why you want the last normally executed shell statement to be "exit 0".  if you omit the exit statement it in this example, and $report_mode is not set, your shell program will give a non-zero return code and appear to have terminated with an error.  in shell the last expression evaluated determines the return code to the os.</div><div><br></div><div>ok, i don't need to do this in python.</div><div><br></div><div>On Thu, Sep 18, 2014 at 1:23 PM, Peter Otten <span dir="ltr"><<a href="mailto:__peter__@web.de" target="_blank">__peter__@web.de</a>></span> wrote:<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">file_path may contain newlines, therefore you should probably use "\0" to<br>separate the records.</blockquote><div><br></div><div>i chose to stick with ascii nul as the default field separator, but i added a --field-separator option in case someone wants human readable output.</div></div><div><br></div><div>style question:  if there is only one, possibly short statement in a block, do folks usually move it up to the line starting the block?</div><div><br></div><div><div><font face="courier new, monospace">  <b>if not S_ISREG( mode ) or S_ISLNK( mode ):</b></font></div><div><font face="courier new, monospace"><b>    return</b></font></div></div><div><br></div><div>vs.</div><div><br></div><div><div>    <font face="courier new, monospace"><b>if not S_ISREG( mode ) or S_ISLNK( mode ): return</b></font></div></div><div><br></div><div>or even:</div><div><br></div><div><div>   <font face="courier new, monospace"><b>with open( file_path, 'rb' ) as f: md5sum = md5_for_file( file_path )</b></font></div></div><div><br></div><div><br></div><div><br></div><div>fyi, here are my changes:</div><div><br></div><div><br></div><div><div><b><font face="courier new, monospace">usage: dupscan [-h] [--start-directory START_DIRECTORY]</font></b></div><div><b><font face="courier new, monospace">               [--field-separator FIELD_SEPARATOR]</font></b></div><div><b><font face="courier new, monospace"><br></font></b></div><div><b><font face="courier new, monospace">scan files in a tree and print a line of information about each regular file</font></b></div><div><b><font face="courier new, monospace"><br></font></b></div><div><b><font face="courier new, monospace">optional arguments:</font></b></div><div><b><font face="courier new, monospace">  -h, --help            show this help message and exit</font></b></div><div><b><font face="courier new, monospace">  --start-directory START_DIRECTORY, -d START_DIRECTORY</font></b></div><div><b><font face="courier new, monospace">                        Specify the root of the filesystem tree to be</font></b></div><div><b><font face="courier new, monospace">                        processed. The default is '.'</font></b></div><div><b><font face="courier new, monospace">  --field-separator FIELD_SEPARATOR, -s FIELD_SEPARATOR</font></b></div><div><b><font face="courier new, monospace">                        Specify the string to use as a field separator in</font></b></div><div><b><font face="courier new, monospace">                        output. The default is the ascii nul character.</font></b></div></div><div><br></div><div><br></div><div><br></div><div><div><font face="courier new, monospace" size="1"><b>#!/usr/bin/python</b></font></div><div><font face="courier new, monospace" size="1"><b><br></b></font></div><div><font face="courier new, monospace" size="1"><b>import argparse</b></font></div><div><font face="courier new, monospace" size="1"><b>import hashlib</b></font></div><div><font face="courier new, monospace" size="1"><b>import os</b></font></div><div><font face="courier new, monospace" size="1"><b><br></b></font></div><div><font face="courier new, monospace" size="1"><b>from platform import node</b></font></div><div><font face="courier new, monospace" size="1"><b>from stat import S_ISREG, S_ISLNK</b></font></div><div><font face="courier new, monospace" size="1"><b><br></b></font></div><div><font face="courier new, monospace" size="1"><b>ASCII_NUL = chr(0)</b></font></div><div><font face="courier new, monospace" size="1"><b><br></b></font></div><div><font face="courier new, monospace" size="1"><b>     # from: <a href="http://stackoverflow.com/questions/1131220/get-md5-hash-of-big-files-in-python">http://stackoverflow.com/questions/1131220/get-md5-hash-of-big-files-in-python</a></b></font></div><div><font face="courier new, monospace" size="1"><b>     # except that i use hexdigest() rather than digest()</b></font></div><div><font face="courier new, monospace" size="1"><b>def md5_for_file( path, block_size=2**20 ):</b></font></div><div><font face="courier new, monospace" size="1"><b>  md5 = hashlib.md5()</b></font></div><div><font face="courier new, monospace" size="1"><b>  with open( path, 'rb' ) as f:</b></font></div><div><font face="courier new, monospace" size="1"><b>    while True:</b></font></div><div><font face="courier new, monospace" size="1"><b>      data = f.read(block_size)</b></font></div><div><font face="courier new, monospace" size="1"><b>      if not data:</b></font></div><div><font face="courier new, monospace" size="1"><b>        break</b></font></div><div><font face="courier new, monospace" size="1"><b>      md5.update(data)</b></font></div><div><font face="courier new, monospace" size="1"><b>  return md5.hexdigest()</b></font></div><div><font face="courier new, monospace" size="1"><b><br></b></font></div><div><font face="courier new, monospace" size="1"><b>def file_info( directory, basename, field_separator=ASCII_NUL ):</b></font></div><div><font face="courier new, monospace" size="1"><b>  file_path = os.path.join( directory, basename )</b></font></div><div><font face="courier new, monospace" size="1"><b>  st = os.lstat( file_path )</b></font></div><div><font face="courier new, monospace" size="1"><b><br></b></font></div><div><font face="courier new, monospace" size="1"><b>  mode = st.st_mode</b></font></div><div><font face="courier new, monospace" size="1"><b>  if not S_ISREG( mode ) or S_ISLNK( mode ): </b></font></div><div><font face="courier new, monospace" size="1"><b>    return</b></font></div><div><font face="courier new, monospace" size="1"><b><br></b></font></div><div><font face="courier new, monospace" size="1"><b>  with open( file_path, 'rb' ) as f:</b></font></div><div><font face="courier new, monospace" size="1"><b>    md5sum = md5_for_file( file_path )</b></font></div><div><font face="courier new, monospace" size="1"><b><br></b></font></div><div><font face="courier new, monospace" size="1"><b>  return field_separator.join( [ thishost, md5sum, str( st.st_dev ), str( st.st_ino ), str( st.st_nlink ), str( st.st_size ), file_path ] )</b></font></div><div><font face="courier new, monospace" size="1"><b><br></b></font></div><div><font face="courier new, monospace" size="1"><b>if __name__ == "__main__":</b></font></div><div><font face="courier new, monospace" size="1"><b>  parser = argparse.ArgumentParser(description='scan files in a tree and print a line of information about each regular file')</b></font></div><div><font face="courier new, monospace" size="1"><b>  parser.add_argument('--start-directory', '-d', default='.', help='''Specify the root of the filesystem tree to be processed.  The default is '.' ''')</b></font></div><div><font face="courier new, monospace" size="1"><b>  parser.add_argument('--field-separator', '-s', default=ASCII_NUL, help='Specify the string to use as a field separator in output.  The default is the ascii nul character.')</b></font></div><div><font face="courier new, monospace" size="1"><b>  args = parser.parse_args()</b></font></div><div><font face="courier new, monospace" size="1"><b><br></b></font></div><div><font face="courier new, monospace" size="1"><b>  start_directory = args.start_directory.rstrip('/')</b></font></div><div><font face="courier new, monospace" size="1"><b>  field_separator = args.field_separator</b></font></div><div><font face="courier new, monospace" size="1"><b><br></b></font></div><div><font face="courier new, monospace" size="1"><b>  thishost = node()</b></font></div><div><font face="courier new, monospace" size="1"><b>  if thishost == '':</b></font></div><div><font face="courier new, monospace" size="1"><b>    thishost='[UNKNOWN]'</b></font></div><div><font face="courier new, monospace" size="1"><b><br></b></font></div><div><font face="courier new, monospace" size="1"><b>  for directory_path, directory_names, file_names in os.walk( start_directory ):</b></font></div><div><font face="courier new, monospace" size="1"><b>    for file_name in file_names:</b></font></div><div><font face="courier new, monospace" size="1"><b>      print file_info( directory_path, file_name, field_separator )</b></font></div></div><div><br></div><div><br></div><div><br></div>-- <br>Live in a world of your own, but always welcome visitors.
</div></div>