adamshields
asked on
Python function to handle multiple file input types for an argument
I previously posted http://www.experts-exchang e.com/Prog ramming/La nguages/Sc ripting/Py thon/Q_268 81841.html but I would now like to take a file, folder or wildcards via command line using a single option/arg. How can the same be achieved using a function? Thanks
ASKER
@pepr: how would this work with my current logic? I am only going to be using the options.filename and doing away with the options.directory argument.
filenames_or_wildcards = []
# remove next line if you do not want allow to run the script without the -f -d
# option, but with arguments
filenames_or_wildcards = args # take all filenames passed in the command line
# if -f was specified add them (in current working directory)
if options.filename is not None:
filenames_or_wildcards.append(options.filename)
# if -d was specified or nothing at all add files from dir
if options.directory is not None:
filenames_or_wildcards.append( os.path.join(options.directory, "*") )
# Now expand all wildcards
# glob.glob transforms a filename or a wildcard in a list of all matches
# a non existing filename will be 'dropped'
all_files = []
for filename_or_wildcard in filenames_or_wildcards:
all_files.extend( glob.glob(filename_or_wildcard) )
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Well, I was typing meanwhile. The myFiles() processes a single argument but it can easily be adjusted to proces or a single argument or a list of arguments. Any single argument could be a file, a dir, a mask.
ASKER
Thanks for the quick response!
Have a look at the modified function:
b.py
It prints:
Notice that the names are not uniqued in the case.
b.py
import glob
import os
import sys
def myFiles(arg):
'''A generator function that diggs all files from the argument.'''
if isinstance(arg, str): # single string
lst = [ arg ] # convert to the list
elif isinstance(arg, list): # list is OK,
lst = arg # no conversion
else:
print 'Unexpected arg:', repr(arg)
sys.exit(1)
# Warning: the arg identifier reused here (not ideal).
for arg in lst:
if os.path.isfile(arg): # for a single file, return the file
yield arg
elif os.path.isdir(arg): # for a directory, return all files
for item in os.listdir(arg): # produces bare names
fname = os.path.join(arg, item) # path + bare name
if os.path.isfile(fname): # only the files are returned
yield fname # no normalization of slashes/backslashes here
else:
for fname in glob.glob(arg): # it could be a mask -- expand it
if os.path.isfile(fname): # only the files are returned
yield os.path.normpath(fname) # normalize slashes/backslashes
print '-' * 70
arg = 'testDir/a.txt' # existing file
print 'Test for', repr(arg)
print list(myFiles(arg))
print '-' * 70
arg = 'testDir/.' # existing directory -- another form
print 'Test for', repr(arg)
print list(myFiles(arg))
print '-' * 70
arg = ['noDir/*.txt', # mask expanding to no file
'testDir/*', # all files from the existing directory
'testDir/?.txt', # one-letter + extension
'testDir/a*.txt', # a-prefixed filenames
'testDir/*a.txt', # a-suffixed filenames
]
print 'Test for', repr(arg)
print list(myFiles(arg))
It prints:
C:\tmp\_Python\adamshields\Q_26901398>python b.py
----------------------------------------------------------------------
Test for 'testDir/a.txt'
['testDir/a.txt']
----------------------------------------------------------------------
Test for 'testDir/.'
['testDir/.\\a.txt', 'testDir/.\\aa.txt', 'testDir/.\\ax.txt', 'testDir/.\\ba.txt', 'testDir/.\\x.txt']
----------------------------------------------------------------------
Test for ['noDir/*.txt', 'testDir/*', 'testDir/?.txt', 'testDir/a*.txt', 'testDir/*a.txt']
['testDir\\a.txt', 'testDir\\aa.txt', 'testDir\\ax.txt', 'testDir\\ba.txt',
'testDir\\x.txt', 'testDir\\a.txt', 'testDir\\x.txt', 'testDir\\a.txt',
'testDir\\aa.txt', 'testDir\\ax.txt', 'testDir\\a.txt', 'testDir\\aa.txt',
'testDir\\ba.txt']
Notice that the names are not uniqued in the case.
ASKER
Great thanks, lastly, if I were using:
def main()
Where would def myFiles(arg): be located, before, after or in the main()?
Thanks
def main()
Where would def myFiles(arg): be located, before, after or in the main()?
Thanks
It does not matter in Python. But it may be good to keep conventions from other languages and put it earlier than main().
Actually, Python interprets the .py file from beginning to the end. However, the first and the only interpretation means compilation. Any def, class or such is converted to the internal object, any other command is interpreted.
Actually, Python interprets the .py file from beginning to the end. However, the first and the only interpretation means compilation. Any def, class or such is converted to the internal object, any other command is interpreted.
ASKER
Okay thanks!
If yes, I suggest to create a generator function that produces the filenames independently on what you pass. Or it could be no file, or the single file, or the files got via expanded mask, or the files from inside the directory. (I know I am repeating the same using the other words.)
Then if you get the argument myArg, the you will use it this way:
Open in new window
Do you want something like this?