Check whether or not directory is in path - python

I'm trying to write a Python function to accomplish the following: given a path and directory, return True only if directory appears somewhere in path.
For example consider the following example:
path = 'Documents/Pictures/random/old/test_image.jpg'
dir = 'random'
This should return True, since the directory random/ occurs somewhere along the path. On the other hand, the following example should return False:
path = 'Documents/Pictures/random_pictures/old/test_image.jpg'
dir = 'random`
This is because the directory random/ does not appear in the path, random_pictures/ does.
Is there a smarter way to do this than simply doing something like this:
def is_in_directory(path, dir):
return '/{0}/'.format(dir) in path
Perhaps with an os or os.path module?

You can use os.path.split to get the directory path then split them and check for existence :
>>> dir = 'random'
>>> dir in os.path.split(path)[0].split('/')
True
And as #LittleQ suggested as a better way you can split your base path with os.path.sep
>>> dir in os.path.split(path)[0].split(s.path.sep)
True

split using os.path.sep os.path.dirname:
from os.path import sep,dirname
def is_in_directory(p, d):
return d in dirname(p).split(sep)
os.path.dirname(path)ΒΆ
Return the directory name of pathname path. This is the first element of the pair returned by passing path to the function split().

Related

How get path of specific parent directory in python

I have path = "dir1/dir2/dir3/file.py"
I need a way to get the full path to dir2 i.e. dir1/dir2.
something like findparent(path, 'dir2').
You can split the path by the target directory, take the first element from the list, and then add the target directory to the target path.
path = "dir1/dir2/dir3/file.py"
def findparent(path: str, dir_: str) -> str:
return path.split(dir_)[0] + dir_
print(findparent(path, 'dir2'))
# dir1/dir2
If you use pathlib and the path actually exists:
path.resolve().parent
Just path.parent also works, purely syntactically, but has some caveats as mentioned in the docs.
To find one specific part of the parent hierarchy, you could iteratively call parent, or search path.parents for the name you need.
Check this out! How to get the parent dir location
My favorite is
from pathlib import Path
Path(__file__).parent.parent.parent # ad infinitum
You can even write a loop to get to dir2, something like this..
from pathlib import Path
goal_dir = "dir2"
current_dir = Path(__file__)
for i in range(10):
if current_dir == goal_dir:
break
current_dir = current_dir.parent
Note: This solution is not the best, you might want to use a while-loop instead and check if there is actually a parent. If you are at root level and there is no parent, then it doesn't exist. But, assuming it exists and you don't have a tree deeper than 10 levels, this works.
Assuming your current work directory is at the same location as your dir1, you can do:
import os
os.path.abspath("dir1/dir2")

How to change to a specific folder using cmd without caring about the whole path?

I am at a specific folder lets say users/personal/project/scripts. Is there a way to go to the project folder without caring about what is before /project, that is without caring about the users/personal/ in a python script?
I am looking for a way, other than
import os
os.chdir('..')
You can use split of os.path module.
import os
import os.path
some_path = '/users/personal/project/scripts'
base_path, child = os.path.split(some_path)
os.chdir(base_path)
You can use the os module with the os.cwd() and os.path.abspath(os.path.join(path, os.pardir)) in order to achieve this. GeeksforGeeks has a great article, which has multiple answers to your question:
https://www.geeksforgeeks.org/get-parent-of-current-directory-using-python/
METHOD 1:
import os
# get current directory
path = os.getcwd()
print("Current Directory", path)
print()
# parent directory
parent = os.path.dirname(path)
print("Parent directory", parent)
METHOD 2:
import os
# get current directory
path = os.getcwd()
print("Current Directory", path)
# prints parent directory
print(os.path.abspath(os.path.join(path, os.pardir)))
METHOD 3:
import os.path
# function to get parent
def getParent(path, levels = 1):
common = path
# Using for loop for getting
# starting point required for
# os.path.relpath()
for i in range(levels + 1):
# Starting point
common = os.path.dirname(common)
# Parent directory upto specified
# level
return os.path.relpath(path, common)
path = 'D:/Pycharm projects / GeeksforGeeks / Nikhil / gfg.txt'
print(getParent(path, 2))
Keep in mind, that you can put these into functions and repeat them the number of parent directories up you need to go, for example you could turn method 1 into:
import os
def get_parent_directory(num_of_parent_directories_to_go_up=1): # Defaults the number of parent directories to go up to one, which mean go one directory up
current_path = os.getcwd()
for i in range(num_of_parent_directories_to_go_up):
current_path = os.path.dirname(current_path)
return current_path
This will output the parent directory of how many times you put into it, which defaults to one.
Example 1:
INPUT: users/personal/project/scripts
CODE: get_parent_directory()
OUTPUT: users/personal/project/
Example 2:
INPUT: users/personal/project/scripts
CODE: get_parent_directory(2)
OUTPUT: users/personal/
Ans you can see how this would go on. Furthermore, this does not error if you give a number larger than parent directories exist and will instead return the root path.
In the function or with what is returned from the example function I provided, you can use os.chdir(path_from_function_here) to change your working directory.
you can use os.getcwd() to get the current path, then find out how many level to go back to project folder, then goto project folder using os.chdir
this will works across variable level deep inside project directory.
for example, current directory either in /users/personal/project/scripts or /users/personal/project/scripts/lib also will back to /users/personal/project
os.path.sep ensure this will works in both windows/linux
curdir = os.getcwd().split(os.path.sep)
project_back_idx = len(curdir) - curdir.index('project') - 1
os.chdir(os.path.sep.join(['..'] * project_back_idx))
# 1 level back - os.chdir('..')
# 2 level back - os.chdir('..//..') and so on

Python - How to use relative paths with os.replace?

I am using the os.replace function to rename a folder. The folder will remain in the same parent directory.
parent_dir = '/Users/my_Username/Desktop/'
old_name = 'foo'
new_name = 'bar'
os.replace(parent_dir + old_name, parent_dir + new_name)
This code works, but feels a little redundant, especially when using long variable names and when calling this function multiple times.
According to the docs,
This function can support specifying src_dir_fd and/or dst_dir_fd to supply paths relative to directory descriptors.
However, I cannot figure out how to pass in the relative path of both folders. I thought it would be something like this:
os.rename(old_name, new_name, src_dir_fd=parent_dir)
But that doesn't work.
How do I pass in a relative path?
You could write something like this:
import os
parent_dir = '/Users/my_Username/Desktop/'
old_name = 'foo.txt'
new_name = 'bar.txt'
with os.open(parent_dir, os.O_RDONLY) as fd:
os.replace(old_name, new_name, src_dir_fd=fd)
Option src_dir_fd accepts a file descriptor (fd), intead of actual path. There is good description in the documentation.

Recursively create directories in python while skipping existing directories

I'm trying to create the following directories:
/autofs/homes/008/gwarner/test1/test2/
/autofs/homes/008/gwarner/test1/test3/
where /autofs/homes/008/gwarner/ already exists and I don't have write access for all of /autofs/homes/008/. When I try running:
dir = '/autofs/homes/008/gwarner/test/test1/test4/test5/'
for root, dirs, files in os.walk(dir, topdown = True):
print root
I get no output at all.
I assume you've tried os.makedirs(), right? Perhaps I'm misunderstanding your requirements, but you say you want to:
Recursively create directories
And the docs for os.makedirs() starts with:
Recursive directory creation function.
You could use the os.path.exists modules.
I would be careful and use both os.path.isdir and os.path.exists to check if the path is a directory before trying to write inside the directory and os.path.exists before overwriting a path.
For example:
>>> import os
>>> os.path.isdir('/home')
True
>>> os.path.isdir('/usr/bin')
True
>>> os.path.isdir('/usr/bin/python')
False
# writing a single, non-recursive path
>>> if not os.path.exists('/home/cinnamon'):
... os.mkdir('/home/cinnamon')
# writing a single, recursive path
>>> if not os.path.exists('/home/alex/is/making/a/really/long/path'):
... os.makedirs('/home/alex/is/making/a/really/long/path')
# now to script the latter
>>> paths = ['/home/alex/path/one', ...]
>>> for path in paths:
>>> if not os.path.exists(path):
>>> os.makedirs(path)
This way, you do not overwrite anything exists, you check if something is a directory before you write in the directory. By design, the system throws an OSError if the path exists, because it does not know HOW you want to handle it.
Do you want to overwrite the path (shutil.rmtree), do you want to store that the path has already been set, or do you want to just skip it? This is for you, the coder, to decide.

Can you set cwd for abspath?

I am trying to expand out a relative path into an absolute path. The relative path will sometimes in include a . which will need to be expanded out from the current working directory. I was wondering if the any standard functions in Python accept a cwd kwarg, like subprocess.popen does.
Optimal Solution
abs_path = os.path.abspath(rel_path, cwd=special_cwd)
Current Solution
# Capture current working directory
previous_cwd = os.getcwd()
# Change to the new working directory
os.chdir(new_cwd)
# Convert relative path to absolute path
abs_path = os.path.abspath(rel_path)
# Change back to previous working directory
os.chdir(previous_cwd)
The current solution seems clunky, is there a better way to accomplish this?
The current solution seems clunky, is there a better way to accomplish this?
You can write your own code as a context manager which changes the directory and then changes back:
>>> from contextlib import contextmanager
>>> #contextmanager
... def cwd(path):
... from os import getcwd, chdir
... cwd = getcwd()
... chdir(path)
... yield
... chdir(cwd)
then the actual code will look much cleaner:
>>> os.getcwd()
'/home/user'
>>> with cwd('/usr/share'):
... print(os.path.abspath('./test'))
...
/usr/share/test
>>> os.getcwd()
'/home/user'

Categories