NeStack
NeStack

Reputation: 2012

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

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'

Upvotes: 6

Views: 6638

Answers (6)

user2514157
user2514157

Reputation: 681

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'

Upvotes: 1

JLD
JLD

Reputation: 89

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.

Upvotes: 1

Zach Favakeh
Zach Favakeh

Reputation: 227

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.

Upvotes: 2

TomNash
TomNash

Reputation: 3288

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'

Upvotes: 1

buran
buran

Reputation: 14273

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

Upvotes: 4

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.

Upvotes: 0

Related Questions