Skip to content

Instantly share code, notes, and snippets.

@zdavkeos
Created July 21, 2011 23:18
Show Gist options
  • Star 7 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save zdavkeos/1098474 to your computer and use it in GitHub Desktop.
Save zdavkeos/1098474 to your computer and use it in GitHub Desktop.
python walk_up - like os.walk, only works its way up instead of down
#!/bin/env python
"""
os.walk is an awesome generator.
However, I needed the same functionality,
only I wanted to walk 'up' the
directory tree.
This allows seaching for files
in directories directly above
a given directory.
"""
import os
from os import path
def walk_up(bottom):
"""
mimic os.walk, but walk 'up'
instead of down the directory tree
"""
bottom = path.realpath(bottom)
#get files in current dir
try:
names = os.listdir(bottom)
except Exception as e:
print e
return
dirs, nondirs = [], []
for name in names:
if path.isdir(path.join(bottom, name)):
dirs.append(name)
else:
nondirs.append(name)
yield bottom, dirs, nondirs
new_path = path.realpath(path.join(bottom, '..'))
# see if we are at the top
if new_path == bottom:
return
for x in walk_up(new_path):
yield x
if __name__ == '__main__':
# tests/demos
#print all files and directories
# directly above the current one
for i in walk_up(os.curdir):
print i
# look for a TAGS file above the
# current directory
for c,d,f in walk_up(os.curdir):
if 'TAGS' in f:
print c
break
@hrieke
Copy link

hrieke commented Apr 9, 2019

Is this code covered by a license?
Thanks

@lambdamusic
Copy link

lambdamusic commented Jun 14, 2019

#python3 version

import os
from os import path

def walk_up(bottom):
    """ 
    mimic os.walk, but walk 'up'
    instead of down the directory tree
    """

    bottom = path.realpath(bottom)

    #get files in current dir
    try:
        names = os.listdir(bottom)
    except Exception as e:
        print(e)
        return


    dirs, nondirs = [], []
    for name in names:
        if path.isdir(path.join(bottom, name)):
            dirs.append(name)
        else:
            nondirs.append(name)

    yield bottom, dirs, nondirs

    new_path = path.realpath(path.join(bottom, '..'))
    
    # see if we are at the top
    if new_path == bottom:
        return

    for x in walk_up(new_path):
        yield x

@rednafi
Copy link

rednafi commented Jan 15, 2020

Here is a naive test via pytest

import pytest

@pytest.fixture(autouse=True)
def make_tmpdir(tmpdir):
    tmp_dir = tmpdir.mkdir("faka")
    return str(tmp_dir)


def test_walk_up(make_tmpdir):
    dirs = list(walk_up(make_tmpdir))
    assert isinstance(dirs[0][0], str)
    assert dirs[0][0].split("/")[-1] == "faka"
    assert dirs[0][1] == []
    assert dirs[0][2] == []

@zdavkeos
Copy link
Author

zdavkeos commented Feb 6, 2020

Thank you to @lambdamusic and @rednafi for keeping this example fresh and alive!

@pombredanne
Copy link

@zdavkeos this code is used in Pipfile FWIW, .... now what's your license?

@derks
Copy link

derks commented Sep 12, 2020

FWIW, I created a library that was inspired by this snippet a long while ago: https://github.com/datafolklabs/backpedal ... it has little traction but my intent is to keep it alive, and well tested. Licensed as BSD-three-clause.

pip install backpedal

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment