3
\$\begingroup\$

R does not support line continuation as Python, and it's disturbing to have long file paths like

/media/user/data/something-not-very-important-but-super-long/some-curious-secret-file.pdf

and can't break it into multiple lines.

The workaround is to use the file.path function:

file.path(
 "/root",
 "folder",
 "file.ods")

Manually editing is tedious, so here is a Python script that does the job for you:

#!/usr/bin/env python3
import sys
x = sys.argv[1]
# split by unix path separator
y = x.split("/")
# get rid of empty strings
y = [i for i in y if i]
# preserve / if it's an absolute path
if x.startswith("/"):
 y[0] = "/" + y[0]
# quote everything
y = ["'" + i + "'" for i in y]
res = "file.path(" + ",\n ".join(y) + ")"
print(res)
200_success
145k22 gold badges190 silver badges478 bronze badges
asked Jan 14, 2015 at 22:00
\$\endgroup\$

2 Answers 2

4
\$\begingroup\$

Always throw things in main:

def main():
 # code
main()

It might seem pointless but it does help with preventing global pollution, which is good if you ever decide to add a function somewhere.

Using

x = sys.argv[1]

is acceptable for a trivial script, but it's not much harder to use docopt and implement a proper command-line parser:

"""
Name Of Program.
Usage: prog.py <pathname>
"""
import docopt
def main():
 args = docopt.docopt(__doc__)
 x = args["<pathname>"]

Trivial, but it gives you --help, error reporting and sane handling of bad input, nearly for free.

This can be simplified a little with pathlib:

parts = pathlib.PurePosixPath(args["<pathname>"]).parts
if len(parts) >= 2 and parts[0] == "/":
 parts = ("/" + parts[1],) + parts[2:]

You can actually use just pathlib.Path but it may assume a Windows format on Windows machines.

Your quoting:

parts = ["'" + i + "'" for i in parts]

should be done with repr:

parts = map(repr, parts)

and the formatting should use .format:

res = "file.path({})".format(",\n ".join(parts))

This gives

#!/usr/bin/env python3
"""
Name Of Program.
Usage: prog.py <pathname>
"""
import docopt
import pathlib
def main():
 args = docopt.docopt(__doc__)
 parts = pathlib.PurePosixPath(args["<pathname>"]).parts
 if len(parts) >= 2 and parts[0] == "/":
 parts = ("/" + parts[1],) + parts[2:]
 args = ",\n ".join(map(repr, parts))
 print("file.path({})".format(args))
main()

Technically PEP 8 says docopt should be separated from pathlib, the second being in the stdlib, but it looks nicer this way for now.

Janne Karila
10.6k21 silver badges34 bronze badges
answered Jan 15, 2015 at 2:49
\$\endgroup\$
2
\$\begingroup\$

This seems quite alright. I have a couple of tips though:

  • Since you use the / in multiple places, it would be good to give it a name.

  • The variable names could be improved: x and y don't tell much about what they are.

  • Instead of "'" + i + "'", it's shorter and perhaps easier to read as "'%s'" % i, though the new style formatting is recommended, so this latter should be written as "'{}'".format(i)

Putting it together:

# use unix path separator
separator = '/'
origpath = sys.argv[1]
parts = origpath.split(separator)
# get rid of empty strings
parts = [item for item in parts if item]
# preserve / if it's an absolute path
if origpath.startswith(separator):
 parts[0] = separator + parts[0]
# quote everything
parts = ["'{}'".format(item) for item in parts]
res = "file.path(" + ",\n ".join(parts) + ")"
print(res)
answered Jan 14, 2015 at 23:00
\$\endgroup\$
2
  • \$\begingroup\$ "Since you use the / in multiple places, it would be good to give it a name." Not sure I agree 'bout that. Also, new style formatting rulez: "'{}'".format(item). \$\endgroup\$ Commented Jan 15, 2015 at 2:22
  • \$\begingroup\$ @Veedrac replacing a magic string literal with a well-named variable is certainly a good thing. You seem to miss the point with the gist, which would only be marginally related if I had named the variable forward_slash. You're right about new style formatting though, updated that in my answer \$\endgroup\$ Commented Jan 15, 2015 at 6:58

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.