A function to copy folder along with its contents python - python

Hi is there a function that copies a parent folder along with all its content to a specified destination in python.
I have used different functions but they seem to copy the contents excluding the parent folder.
Many thanks

shutil.copytree comes to mind immediately, but your issue is that copying directory foo in bar doesn't create bar/foo.
My proposal:
import shutil,os
def copytree2(source,dest):
os.mkdir(dest)
dest_dir = os.path.join(dest,os.path.basename(source))
shutil.copytree(source,dest_dir)
first create destination
then generate destination dir, which is the destination added source basename
perform copytree with the new destination, so source folder name level appears under dest
There's no subtle check about dest directory already exist or whatnot. I'll let you add that if needed (using os.path.isdir(dest) for instance)
Note that functions from shutil come with a note which encourages users to copy and modify them to better suit their needs.

In python 3.* we can use shutil
import shutil
old_folder = "D:/old_folder"
new_folder = "D:/new_folder"
shutil.copytree(old_folder, new_folder, dirs_exist_ok=True)
dirs_exist_ok=True is for ignoring the exception when the folder already exists in the new location.

Simply append the source directory you want to copy in the destination:
import shutil
shutil.copytree("source", "destination/source")
If you do not have fixed strings then use os.path.basename() to determine basename and combine it in the destination with os.path.join()
import os.path
import shutil
source = "/Projekte/python/source"
shutil.copytree(source, os.path.join("destination", os.path.basename(source)))

import shutil
shutil.copytree(srcDir, dst, symlinks=False, ignore=None)

Related

How do I copy all folder contents from one location to another location in Python?

I have been trying to make a python file that will copy contents from one folder to another. I would like it to work on any Windows system that I run it on. It must copy ALL things .
i need solution to this problem.
You can use the copytree function of the shutil library:
import shutil
source_folder = "C:\\Users\\user1\\source_folder"
destination_folder = "C:\\Users\\user1\\destination_folder"
# Copy the contents of the source folder to the destination folder
shutil.copytree(source_folder, destination_folder)

Is there a way, in python, I can copy a file in a directory and duplicate it in the same directory with a different name?

I want to be able to take a file and duplicate it in the same directory with a different name, but I can't figure out how to change the name while copying so it doesn't give me and error that the file already exists or changes the name of the original file.
shutil.copy() can do that if you specify the destination filename as well as destination folder:
import shutil
shutil.copy(r'c:\temp\file1.txt', r'c:\temp\file2.txt')
Adding on to TessellatingHeckler's answer, if you have a file with an arbitrary directory, you can use os.path.dirname and os.path.join to create a new filename in the same directory:
import os
import shutil
original = r'c:\temp\file1.txt'
original_dir = os.path.dirname(original) # r'c:\temp'
new_name = 'file2.txt'
new_path = os.path.join(original_dir, new_name) # r'c:\temp\file2.txt'
shutil.copy(original, new_path)
You could of course do that more compactly if you wish. You'll also notice from the shutil.copy() docs that shutil features multiple different copying methods, each one with pros and cons. For example, shutil.copy2() attempts to preserve metadata. It's up to you to decide which method is best for your situation.

copying specific files with shutil()

I have a folder with 7500 images. I need to copy the first 600 images to a new folder using the shutil module in Python.
I tried to look for relevant stuff on the net but the usage of the paths is a bit confusing. What exactly should be my sequence of commands? I guess it will start like:
import os
import shutil
l=os.listdir(path)
for file in l[0:600]:
Edit: after having clarification on what shutil.copy() does, I came up with:
import os
import shutil
l=os.listdir(path)
for file in l[0:600]:
shutil.copy(file, destination, *, follow_symlinks = True)
But it's highlighting the comma after *, and giving the error iterable argument unpacking follows keyword argument unpacking. What's going wrong in the syntax?
Well, os.listdir() will return files randomly sorted, one thing you could do is that you can call os.stat(file).st_mtime on each file which will return timestamp when that file was last modified and then you can sort the files by that time to get first/last files. But it really depends on your use-case and how you interpret what first files are for you. But when it comes to shutil library you can just call:
for file in l[0:600]:
shutil.copy(file, f'./destination/{file}')
which will copy 600 files into directory that is in your current directory and named 'destination'.
os.listdir(path) will list files and sub direcotries in your directory you're searching.
I'm making the assumption that all you're files will be .jpg so I would use the glob module.
import glob
path = "D:Pictures\*.jpg"
destination = r"E:\new_pictures\\"
files = glob.glob(path)
for f in sorted(files)[:600]:
shutil.copy(f, destination)

Create directories based on filenames

I am an absolute beginner to programming so I apologize if this is really basic. I've looked at other questions that appear to be related, but haven't found a solution to this particular problem--at least not that I can understand.
I need to generate a list of files in a directory; create a separate directory for each of those files with the directory name being based on each file's name; and put each file in its corresponding directory.
You should have a look at the glob, os and shutil libraries.
I've written an example for you. This will remove the file extension of each file in a given folder, create a new subdirectory, and move the file into the corresponding folder, i.e.:
C:\Test\
-> test1.txt
-> test2.txt
will become
C:\Test\
-> test1\
-> test1.txt
-> test2\
-> test2.txt
Code:
import glob, os, shutil
folder = 'C:/Test/'
for file_path in glob.glob(os.path.join(folder, '*.*')):
new_dir = file_path.rsplit('.', 1)[0]
os.mkdir(os.path.join(folder, new_dir))
shutil.move(file_path, os.path.join(new_dir, os.path.basename(file_path)))
This will throw an error if the folder already exist. To avoid that, handle the exception:
import glob, os, shutil
folder = 'C:/Test/'
for file_path in glob.glob(os.path.join(folder, '*.*')):
new_dir = file_path.rsplit('.', 1)[0]
try:
os.mkdir(os.path.join(folder, new_dir))
except WindowsError:
# Handle the case where the target dir already exist.
pass
shutil.move(file_path, os.path.join(new_dir, os.path.basename(file_path)))
PS: This will not work for files without extensions. Consider using a more robust code for cases like that.
Here is some advice on listing files using Python.
To create a directory, use os.mkdir (docs). To move a file, use os.rename (docs) or shutil.move (docs).

Creating a relative symlink in python without using os.chdir()

Say I have a path to a file:
/path/to/some/directory/file.ext
In python, I'd like to create a symlink in the same directory as the file, that
points to the file. I'd like to end up with this:
/path/to/some/directory/symlink -> file.ext
I can do this fairly easily using os.chdir() to cd into the directory and
create the symlinks. But os.chdir() is not thread safe, so I'd like to avoid
using it. Assuming that the current working directory of the process is not
the directory with the file (os.getcwd() != '/path/to/some/directory'),
what's the best way to do this?
I guess I could create a busted link in whatever directory I'm in, then
move it to the directory with the file:
import os, shutil
os.symlink('file.ext', 'symlink')
shutil.move('symlink', '/path/to/some/directory/.')
Is there a better way to do this?
Note, I don't want to end up with is this:
/path/to/some/directory/symlink -> /path/to/some/directory/file.ext
You can also use os.path.relpath() so that you can use symlinks with relative paths. Say your script is in a directory foo/ and this directory has subdirectories src/ and dst/, and you want to create relative symlinks in dst/ to point to the files in src/. To do so, you can do:
import os
from glob import glob
for src_path in glob('src/*'):
os.symlink(
os.path.relpath(
src_path,
'dst/'
),
os.path.join('dst', os.path.basename(src_path))
)
Listing the contents of dst/ then shows:
1.txt -> ../src/1.txt
2.txt -> ../src/2.txt
Relative symlinks are useful for if you want to create a tarball of the whole foo directory tree, as I don't believe tar updates symlinks to point to the relative path inside of the generated tarball.
You could just set the second argument to the destination, like:
import os
os.symlink('file.ext', '/path/to/some/directory/symlink')
python function to create a relative symlink:
def relative_symlink(src, dst):
dir = os.path.dirname(dst)
Src = os.path.relpath(src, dir)
Dst = os.path.join(dir, os.path.basename(src))
return os.symlink(Src, Dst)
Nowadays, this can be accomplished using pathlib
from pathlib import Path
target = Path('../target.txt')
my_symlink = Path('symlink.txt')
my_symlink.symlink_to(target)
where target is a relative Path or str.

Categories