How to insert a directory in the middle of a file path in Python?
Asked Answered
O

6

6

I want to insert a directory name in the middle of a given file path, like this:

directory_name = 'new_dir'
file_path0 = 'dir1/dir2/dir3/dir4/file.txt'
file_path1 = some_func(file_path0, directory_name, position=2)
print(file_path1)
>>> 'dir1/dir2/new_dir/dir3/dir4/file.txt'

I looked through the os.path and pathlib packages, but it looks like they don't have a function that allows for inserting in the middle of a file path. I tried:

import sys,os
from os.path import join

path_ = file_path0.split(os.sep)
path_.insert(2, 'new_dir')
print(join(path_))

but this results in the error

"expected str, bytes or os.PathLike object, not list"

Does anyone know standard python functions that allow such inserting in the middle of a file path? Alternatively - how can I turn path_ to something that can be processed by os.path. I am new to pathlib, so maybe I missed something out there


Edit: Following the answers to the question I can suggest the following solutions:

1.) As Zach Favakeh suggests and as written in this answer just correct my code above to join(*path_) by using the 'splat' operator * and everything is solved.

2.) As suggested by buran you can use the pathlib package, in very short it results in:

from pathlib import PurePath

path_list = list(PurePath(file_path0).parts)
path_list.insert(2, 'new_dir')
file_path1 = PurePath('').joinpath(*path_list)

print(file_path1)
>>> 'dir1/dir2/new_dir/dir3/dir4/file.txt'
Oubre answered 19/8, 2019 at 19:6 Comment(2)
I don't think this is directly related to your problem, but FYI: you don't need to import numpy to insert a value into a list. my_list.insert(index, value) works fine on its own.Mannie
@Mannie Thanks for the comment, it doesn't change the result, but it makes more sense to use your simpler suggestion, so I corrected my codeOubre
S
2

Since you want to use join on a list to produce the pathname, you should do the following using the "splat" operator: Python os.path.join() on a list

Edit: You could also take your np array and concatenate its elements into a string using np.array2string, using '/' as your separator parameter:https://docs.scipy.org/doc/numpy-1.14.0/reference/generated/numpy.array2string.html

Hope this helps.

Self answered 19/8, 2019 at 19:15 Comment(2)
The question is about inserting a string in another string (which happens to be a path, not necessarily to an existing file, not necessarily on an accessible disk...). This has nothing to do with navigating existing directories.Oestrone
Your suggestion of np.array2string works somehow, but it returns strings of the form ['dir1'/'dir2'/'new_dir'/'dir3'/'dir4'/'file.tx']', so I need to also get rid of the quotation signs. On the other hand your reference to os.path.join() on a list, and using os.path.join(*file_path_list), resolves the error message in my question and solves my problem. If you put this reference to the top of your post I can accept it as the answer.Oubre
P
4

Take a look at pathlib.PurePath.parts. It will return separate components of the path and you can insert at desired position and construct the new path

>>> from pathlib import PurePath
>>> file_path0 = 'dir1/dir2/dir3/dir4/file.txt'
>>> p = PurePath(file_path0)
>>> p.parts
('dir1', 'dir2', 'dir3', 'dir4', 'file.txt')
>>> spam = list(p.parts)
>>> spam.insert(2, 'new_dir')
>>> new_path = PurePath('').joinpath(*spam)
>>> new_path
PurePosixPath('dir1/dir2/new_dir/dir3/dir4/file.txt')

This will work with path as a str as well as with pathlib.Path objects

Pedraza answered 19/8, 2019 at 19:17 Comment(2)
Thanks, it is indeed a possible solution! I made an edit to my question summarizing your code as a TLDR for future readersOubre
Looks like the cleanest solution to me. Also works great with spam.insert(-1, 'new_dir') to insert a folder directly before the last subfolder, as I needed it.Curio
S
2

Since you want to use join on a list to produce the pathname, you should do the following using the "splat" operator: Python os.path.join() on a list

Edit: You could also take your np array and concatenate its elements into a string using np.array2string, using '/' as your separator parameter:https://docs.scipy.org/doc/numpy-1.14.0/reference/generated/numpy.array2string.html

Hope this helps.

Self answered 19/8, 2019 at 19:15 Comment(2)
The question is about inserting a string in another string (which happens to be a path, not necessarily to an existing file, not necessarily on an accessible disk...). This has nothing to do with navigating existing directories.Oestrone
Your suggestion of np.array2string works somehow, but it returns strings of the form ['dir1'/'dir2'/'new_dir'/'dir3'/'dir4'/'file.tx']', so I need to also get rid of the quotation signs. On the other hand your reference to os.path.join() on a list, and using os.path.join(*file_path_list), resolves the error message in my question and solves my problem. If you put this reference to the top of your post I can accept it as the answer.Oubre
T
1

Solution using regex. The regex will create groups of the following

[^\/]+   - non-'/' characters(i.e. directory names)
\w+\.\w+ - word characters then '.' then word characters (i.e. file name)
import re

directory_name = 'new_dir'
file_path0 = 'dir1/dir2/dir3/dir4/file.txt'
position = 2

regex = re.compile(r'([^\/]+|\w+\.\w+)')
tokens = re.findall(regex, file_path0)
tokens.insert(position, directory_name)
file_path1 = '/'.join(tokens)

Result:

'dir1/dir2/new_dir/dir3/dir4/file.txt'
Tena answered 19/8, 2019 at 19:48 Comment(1)
and ... Windows? This really doesn’t look like a job for the regex hammer to me. You can split on os.path.sep easily enough.Regal
A
1

Your solution has only one flaw. After inserting the new directory in the path list path_.insert(2, 'new_dir')you need to call os.path.join(*path_) to get the new modified path. The error that you get is because you are passing a list as parameter to the join function, but you have to unpack it.

Arturoartus answered 27/2, 2020 at 16:43 Comment(0)
F
1

In my case, I knew the portion of path that would precede the insertion point (i.e., "root"). However, the position of the insertion point was not constant due to the possibility of having varying number of path components in the root path. I used Path.relative_to() to break the full path to yield an insertion point for the new_dir.

from pathlib import Path

directory_name = Path('new_dir')
root = Path('dir1/dir2/')
file_path0 = Path('dir1/dir2/dir3/dir4/file.txt')

# non-root component of path
chld = file_path0.relative_to(root)
file_path1 = root / directory_name / chld
print(file_path1)

Result:
'dir1/dir2/new_dir/dir3/dir4/file.txt'

Foregather answered 11/7, 2020 at 22:20 Comment(0)
D
0

I made a try with your need:

directory_name = '/new_dir'

file_path0 = 'dir1/dir2/dir3/dir4/file.txt'

before_the_newpath = 'dir1/dir2'

position = file_path0.split(before_the_newpath)

new_directory = before_the_newpath + directory_name + position[1]

Hope it helps.

Dryly answered 19/8, 2019 at 19:17 Comment(1)
Thanks for the answer, it works. Though it requires that I explicitly specify before_the_newpath, so it is not exactly what I want - I want to just give the position where I want to place the new element in the pathOubre

© 2022 - 2024 — McMap. All rights reserved.