2

I already have this piece of functioning code, but after writing it I did feel the urge to scream "It's alive, it's alive!".

What I want to do is get the folder which has the folder "modules" as its parent folder, e.g. from /home/user/puppet/modules/impuls-test/templates/apache22/ I want /home/user/puppet/modules/impuls-test/

What I came up with is the following:

user@server:~/puppet/modules/impuls-test/templates/apache22$ python
Python 2.4.2 (#1, Apr 13 2007, 15:38:32)
[GCC 4.1.0 (SUSE Linux)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import os
>>> cwd = os.getcwd()
>>> path = cwd
>>> print "cwd: %s" % cwd
cwd: /home/user/puppet/modules/impuls-test/templates/apache22
>>> for i in xrange(len(cwd.split('/'))):
...     (head, tail) = os.path.split(path)
...     print "head: %s" % head
...     print "tail: %s" % tail
...     if tail == 'modules':
...         moduleDir = head + '/modules/' + cwd.split('/')[i+2] + '/'
...         print "moduleDir: %s" % moduleDir
...         break
...     else:
...         path = head
...
head: /home/user/puppet/modules/impuls-test/templates
tail: apache22
head: /home/user/puppet/modules/impuls-test
tail: templates
head: /home/user/puppet/modules
tail: impuls-test
head: /home/user/puppet
tail: modules
moduleDir: /home/user/puppet/modules/impuls-test/

I get the current working directory and use the os.path.split so long until it reaches the modules folder. Using the normal string.split function to iterate over the cwd, I can then append the moduleDir from the original cwd.split('/') array to the current head.

Can someone tell me a better/pythonic way to do this? Sure I can check if the current head ends with modules and then append the current tail, but that would only make the loop break faster and would still be ugly.

4 Answers 4

8
path = "/home/user/puppet/modules/impuls-test/templates"
components = path.split(os.sep)
print str.join(os.sep, components[:components.index("modules")+2])

prints

/home/user/puppet/modules/impuls-test
Sign up to request clarification or add additional context in comments.

5 Comments

Just a note that this solution (similarly to the OP's) is OS-specific. Path splitting by textual "/" won't work on Windows
@Eli: My first attempt was to use os.path.pathsep, which turned out to be wrong, so I just used /. Now I took the time to look up the correct name.
++. BTW, it's also available just as os.sep
thanks for this elegant solution, I'm glad to replace my abomination with this.
It's always wise to call normpath() (and occasionally normcase() as well) before any path manipulation. On Windows, for example, that will convert a forward slash (os.altsep) to a backward one (os.sep). It will also remove repeating path separators and dot directories, which is usually a good thing.
5

Since os.path.normpath handles the ".." operator, you could just tack on a ".." and let normpath do the work:

>>> path = "/home/user/puppet/modules/impuls-test/templates"
>>> os.path.normpath(os.path.join(path, ".."))
'/home/user/puppet/modules/impuls-test'

3 Comments

The problem wasn't getting a path that was normalized or windows friendly, but to find out out many folders I had to go back to get to the module directory.
xorpaul: Ah, sorry, I didn't read the question carefully enough.
Dunno if that helped the OP, but knowing that I can apply ".." using normpath helped me a lot! +1
1

You could use a regular expression

>>> import re
>>> print re.findall(r'(/.*?/modules/(.*?)/).*','/hello/modules/foo/bye')[0]
('/hello/modules/foo/', 'foo')

Comments

0

Similar to Sven's (original) answer but more portable and with error handling...

>>> import os
>>> cwd = '/home/user/puppet/modules/impuls-test/templates/apache22'
>>> directories = cwd.split(os.sep)
>>> try:
...     modules_depth = directories.index('modules')
...     print(os.sep.join(directories[:modules_depth + 2]))
... except ValueError:
...     print('Could not find "modules"')
... 
/home/user/puppet/modules/impuls-test

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.