New folder that is created inside the current directory - python

I have a program in Python that during the processes it creates some files. I want the program to recognize the current directory and then then creates a folder inside the directory, so that the created files will be put in that directory.
I tried this:
current_directory = os.getcwd()
final_directory = os.path.join(current_directory, r'/new_folder')
if not os.path.exists(final_directory):
os.makedirs(final_directory)
But it doesn't give me what I wanted. It seems that the second line is not working as I wanted. Can anybody help me to solve the problem?

think the problem is in r'/new_folder' and the slash (refers to the root directory) used in it.
Try it with:
current_directory = os.getcwd()
final_directory = os.path.join(current_directory, r'new_folder')
if not os.path.exists(final_directory):
os.makedirs(final_directory)
That should work.

One thing to note is that (per the os.path.join documentation) if an absolute path is provided as one of the arguments, the other elements are thrown away. For instance (on Linux):
In [1]: import os.path
In [2]: os.path.join('first_part', 'second_part')
Out[2]: 'first_part/second_part'
In [3]: os.path.join('first_part', r'/second_part')
Out[3]: '/second_part'
And on Windows:
>>> import os.path
>>> os.path.join('first_part', 'second_part')
'first_part\\second_part'
>>> os.path.join('first_part', '/second_part')
'/second_part'
Since you include a leading / in your join argument, it is being interpreted as an absolute path and therefore ignoring the rest. Therefore you should remove the / from the beginning of the second argument in order to have the join perform as expected. The reason you don't have to include the / is because os.path.join implicitly uses os.sep, ensuring that the proper separator is used (note the difference in the output above for os.path.join('first_part', 'second_part').

Related

Python: How to add path separator to beginning of path

I'm looking for the cleanest way to add a path separator to the beginning of a relative path if it's not already there.
So for example my/path should result in /my/path/.
The way I do it now is the following:
import os
os.sep+'my/path'
This approach works but when a non relative path is passed it will also add the separator which is something I want to avoid.
Suggestions?
Try os.path.join with the root directory as its first argument.
>>> import os
>>> os.path.join('/', '/tmp')
/tmp
>>> os.path.join('/', 'tmp')
/tmp

list of jpeg files in nested subdirectories

I use the following python code to get list of jpg files in nested subdirectories which are in parent directory.
import glob2,os
all_header_files = glob2.glob(os.path.join('Path/to/parent/directory','/**/*.jpg'))
However, I get nothing but when I cd into the parent directory and I use the following python code then I get the list of jpeg files.
import glob2
all_header_files = glob2.glob('./**/*.jpg')
How can I get the result with the absolute path?(first version)
You have an extra slash.
The os.path.join will insert the filepath separators for you, so you should think of it as this to get the correct directory
join('Path/to/parent directory' , '**/*.jpg')
Even more accurately,
parent = os.path.join('Path', 'to', 'parent directory')
os.path.join(parent, '**/*.jpg')
If you are trying to use your Home directory, see os.path.expanduser
In [10]: import os, glob
In [11]: glob.glob(os.path.join('~', 'Downloads', "**/*.sh"))
Out[11]: []
In [12]: glob.glob(os.path.expanduser(os.path.join('~', 'Downloads', "**/*.sh")))
Out[12]:
['/Users/name/Downloads/dir/script.sh']
You should not join with the trailing slash as you'll end up with the root. You can debug by printing out the resulting path before passing it to glob.
Try to change your code like this (note the dot):
import glob2,os
all_header_files = glob2.glob(os.path.join('Path/to/parent directory','./**/*.jpg'))
os.path.join() joins paths in an intelligent way.
os.path.join('Path/to/anything','/**/*.jpg'))
resolves to '/**/*.jpg' since '/**/*.jpg' is any path, ever.
Change the '/**/*.jpg' to '**/*.jpg' and it should work.
In cases like this, I recommend to always try out the result of a certain function within the python command line. At least, this is how I found out the issue here.
The problem with the code you have posted lies in the use of os.path.join.
In the documentation it says for os.path.join(path, *paths):
If a component is an absolute path, all previous components are thrown away and joining continues from the absolute path component.
In your case, the component /**/*.jpg is an absolute path, as it starts with a /. Consequently your initial input /Path/to/parent directory is being truncated by the call to the join function. (https://docs.python.org/3.5/library/os.path.html#os.path.join)
I have locally tested the joining part with python3 and for me it is the case, that using os.path.join(any_path, "/**/*.pdf") returns the string '/**/*.pdf'.
The fix for this error is:
import glob2,os
all_header_files = glob2.glob(os.path.join('Path/to/parent directory','**/*.jpg'))
This returns the path 'Path/to/parent directory/**/*.jpg'

Relative path in Python

I'm writing some python code to generate the relative path. Situation need to be considered:
Under the same folder. I want "." or ".\", both of tham are ok for me.
Other folder. I want like ".\xxx\" and "..\xxx\xxx\"
os.path.relpath() will generate the relative path, but without .\ at the beginning and \ in the end. We can add \ in the end by using os.path.join(dirname, ""). But i can't figure out how to add ".\" at the beginning without impacting the first case when they are under the same folder and "..\xxx\xxx\".
It will give you relative path
import os
dir = os.path.dirname(__file__)
filename = os.path.join(dir,'Path')
The relpath() function will produce the ".." syntax given the appropriate base to start from (second parameter). For instance, supposing you were writing something like a script generator that produces code using relative paths, if the working directory is as the second parameter to relpath() as below indicates, and you want to reference in your code another file in your project under a directory one level up and two deep, you'll get "../blah/blah".. In the case where you want to prefix paths in the same folder, you can simply do a join with ".". That will produce a path with the correct OS specific separator.
print(os.path.relpath("/foo/bar/blah/blah", "/foo/bar/baz"))
>>> ../blah/blah
print(os.path.join('.', 'blah'))
>>> ./blah

Moving up one directory in Python

Is there a simple way to move up one directory in python using a single line of code? Something similar to cd .. in command line
>>> import os
>>> print os.path.abspath(os.curdir)
C:\Python27
>>> os.chdir("..")
>>> print os.path.abspath(os.curdir)
C:\
Using os.chdir should work:
import os
os.chdir('..')
Obviously that os.chdir('..') is the right answer here. But just FYI, if in the future you come across situation when you have to extensively manipulate directories and paths, here is a great package (Unipath) which lets you treat them as Python objects: https://pypi.python.org/pypi/Unipath
so that you could do something like this:
>>> from unipath import Path
>>> p = Path("/usr/lib/python2.5/gopherlib.py")
>>> p.parent
Path("/usr/lib/python2.5")
>>> p.name
Path("gopherlib.py")
>>> p.ext
'.py'
Well.. I'm not sure how portable os.chdir('..') would actually be. Under Unix those are real filenames. I would prefer the following:
import os
os.chdir(os.path.dirname(os.getcwd()))
That gets the current working directory, steps up one directory, and then changes to that directory.
In Python 3.4 pathlib was introduced:
>>> from pathlib import Path
>>> p = Path('/etc/usr/lib')
>>> p
PosixPath('/etc/usr/lib')
>>> p.parent
PosixPath('/etc/usr')
It also comes with many other helpful features e.g. for joining paths using slashes or easily walking the directory tree.
For more information refer to the docs or this blog post, which covers the differences between os.path and pathlib.
Although this is not exactly what OP meant as this is not super simple, however, when running scripts from Notepad++ the os.getcwd() method doesn't work as expected. This is what I would do:
import os
# get real current directory (determined by the file location)
curDir, _ = os.path.split(os.path.abspath(__file__))
print(curDir) # print current directory
Define a function like this:
def dir_up(path,n): # here 'path' is your path, 'n' is number of dirs up you want to go
for _ in range(n):
path = dir_up(path.rpartition("\\")[0], 0) # second argument equal '0' ensures that
# the function iterates proper number of times
return(path)
The use of this function is fairly simple - all you need is your path and number of directories up.
print(dir_up(curDir,3)) # print 3 directories above the current one
The only minus is that it doesn't stop on drive letter, it just will show you empty string.
A convenient way to move up multiple directories is pathlib:
from pathlib import Path
full_path = "C:\Program Files\Python37\lib\pathlib.py"
print(Path(full_path).parents[0])
print(Path(full_path).parents[1])
print(Path(full_path).parents[2])
print(Path(full_path).parents[3])
print([str(Path(full_path).parents[i]) for i in range(4)])
output:
C:\Program Files\Python37\lib
C:\Program Files\Python37
C:\Program Files
C:\
['C:\\Program Files\\Python37\\lib', 'C:\\Program Files\\Python37', 'C:\\Program Files', 'C:\\']
Combine Kim's answer with os:
p=Path(os.getcwd())
os.chdir(p.parent)

How can you use os.chdir to go to a path minus the last step of it?

For example, a method is passed a path as a parameter, this path might be "C:/a/b/c/d", what if I want to use os.chdir() to change to C:/a/b/c (without the last folder)? Can os.chdir() take the ".." command?
os.chdir() can take '..' as argument, yes. However, Python provides a platform-agnostic way: by using os.pardir:
os.chdir(os.pardir)
You could use os.path.dirname:
In [1]: import os.path
In [2]: os.path.dirname('C:/a/b/c/d')
Out[2]: 'C:/a/b/c'
edit: It's been pointed out that this doesn't remove the last component if the path ends with a slash. As a more robust alternative, I propose the following:
In [5]: os.path.normpath(os.path.join('C:/a/b/c/d', '..'))
Out[5]: 'C:/a/b/c'
In [6]: os.path.normpath(os.path.join('C:/a/b/c/d/', '..'))
Out[6]: 'C:/a/b/c'
The '..' can be replaced with os.path.pardir to make the code even more portable (at least theoretically).
The os.path module has some functions that are useful for this sort of thing.
os.path.normpath() can be used to convert a path containing references like .. to an absolute path. This would ensure consistent behaviour regardless of how the operating system handles paths.
os.chdir(os.path.normpath("C:/a/b/c/..")) should accomplish what you want.

Categories