Bob McBobson
Bob McBobson

Reputation: 914

How should I get a user to indicate a file path to a directory in a command line program?

I am developing a command line program that requires the user to indicate a number of arguments for the Namespace object, and I am right now I am unsure how to design an argument that would allow the user to indicate the file path to a directory that would contain some text files required by the program to run.

Because I am trying to make this command line program portable (i.e. it can work on Linux, Mac, and Windows), I am not sure how I should design the argument to allow users from different platforms to indicate their pertinent file path, since a file path in Windows must utilize back slashes, as opposed to file paths in Mac or Linux.

How should I go about designing the argument as set up below?

import argparse
from os import path

Parser = argparse.ArgumentParser(prog= "Parser")
Parser.description= "This program helps with stuff blah blah blah"

Parser.add_argument("-input_dir", help= "Please indicate the file path that points to the location of the input text files.")

Parser.add_argument("-input_text", help= "Please indicate the specific text file you want to analyze.")

args= Parser.parse_args()

file_path= args.input_dir
text_file= path.join(file_path, args.input_text)

ADDENDUM

I should note that, what I am trying to accomplish is allow the user to type their file path into the command line with the other arguments, so that their input would look something like:

python testcript.py -input_dir ~/Documents/Input_Directory -input_text somefile.txt

and would still work on multiple platforms.

Upvotes: 0

Views: 1632

Answers (2)

SethMMorton
SethMMorton

Reputation: 48755

You are seriously over-thinking this. It sounds that at the heart of the question is a lack of confidence that os.path actually works cross-platform. Let me assure you, it does! This module has been around for 27 years(!), working on both Windows and UNIX without issue.

Rather than assuming something won't work and then preemptively searching for a workaround (that possibly involves reinventing the wheel), you should instead test it out and see if it works or not. In the future this will save a lot of heartburn worrying about non-issues.

In one of the comments you expressed concern about being able to separate the filename from the directory in a cross-platform way, which is why you want the user to give them independently. This is incorrect thinking. The sane way to approach this would be to just get the full path from the user and break it yourself (users hate doing extra work if not necessary).

import argparse
import os.path

Parser = argparse.ArgumentParser(prog= "Parser")
Parser.description= "This program helps with stuff blah blah blah"

# Added required=True since I imagine you need this path...
Parser.add_argument("-text-file", help= "Please indicate the path to the text file.", required=True)

args= Parser.parse_args()

def make_path_sane(p):
    """Function to uniformly return a real, absolute filesystem path."""
    # ~/directory -> /home/user/directory
    p = os.path.expanduser(p)
    # A/.//B -> A/B
    p = os.path.normpath(p)
    # Resolve symbolic links
    p = os.path.realpath(p)
    # Ensure path is absolute
    p = os.path.abspath(p)
    return p

text_file = make_path_sane(args.text_file)
input_dir = os.path.dirname(text_file)
input_text = os.path.basename(text_file)
print text_file
print input_dir
print input_text

With this setup, the user can choose to give a full path, relative path, or just the file name itself and it will always work! On any file system!

% python2 parse.py -text-file ~/directory/file.txt
/home/smmorton/directory/file.txt
/home/smmorton/directory
file.txt

% python2 parse.py -text-file /home/smmorton/directory/file.txt
/home/smmorton/directory/file.txt
/home/smmorton/directory
file.txt

% python2 parse.py -text-file directory/file.txt
/home/smmorton/directory/file.txt
/home/smmorton/directory
file.txt

% cd ~/directory
% python2 parse.py -text-file file.txt
/home/smmorton/directory/file.txt
/home/smmorton/directory
file.txt

% python2 parse.py -text-file ../directory/./file.txt
/home/smmorton/directory/file.txt
/home/smmorton/directory
file.txt

If you were using Python >= 3.4, I would recommend you use pathlib instead of os.path.

Upvotes: 3

Mohamed Moanis
Mohamed Moanis

Reputation: 507

You can use os.path.join(input_dir, "file1.txt") and it will handle all OS specific issues. You have correctly initialized the parser, use the input directory and the os.path.join also os.path.exists to open your input files.

Quoting the reference: https://docs.python.org/2/library/os.path.html

Since different operating systems have different path name conventions, there are several versions of this module in the standard library. The os.path module is always the path module suitable for the operating system Python is running on, and therefore usable for local paths. However, you can also import and use the individual modules if you want to manipulate a path that is always in one of the different formats.

Upvotes: 0

Related Questions