Rename Single .txt File In Multiple Subdirectories - python

I have ~60 subdirectories in a single directory. Each of these contain thousands of files, but they all contain a file named test_all_results.txt.
What I would like to do is to rename each test_all_results.txt file so that it now has the name:
foldername_all_results.txt
What is the best way to do this?

Easily accomplished using Python os interface.
Assuming you are currently in the main directory:
import os
#get a list of all sub directories
subdir = os.listdir()
for dir in subdir:
if os.path.isdir(dir): #check if directory
os.chdir(dir) #move to sub directory
os.rename('test_all_results.txt', 'foldername_all_results.txt')
os.chdir('..') #return to main directory

Using python in Linux, make this:
import os
os.system("mv old_name.txt new_name.txt")
You can automatize with a loop, renaming all filenames.

You can do:
(change your code accordingly)
import os
# current directory is the target
direct = "."
for path, dirs, files in os.walk(direct):
for f in files:
if os.path.splitext(f)[0] == "test_all_results.txt":
os.rename(os.path.join(path, f), os.path.join(path, "foldername_all_results.txt"))

There's an answer that tells you to use the os.system() method, if you do decide to call Linux commands from Python, I'd advise that you use the subprocess module instead.
Here's how you'd run the mv command with two arguments using subprocess.call:
import subprocess
subprocess.call(["mv", "filename.txt", "new-name.txt"])
INFO: here's an old (but relevant) article that explains why it's dangerous to use these methods.
Good luck.

Related

How do I delete multiple files in a folder?

I wanted to ask the forum how can I delete multiple files in a folder using Python. I tried using the import os module along with os.unlink() module, but it doesn't work. Any help would be greatly appreciated.
Most likely it's because the filename used in the os.unlink(filename) isn't a full path to the file (os.listdir() just returns a sequence of filenames). You probably need to use os.path.join() to prefix the 'c:\\users\\user1' folder to it first.
Something along these lines:
import os
folder = 'c:\\users\\user1\\Pictures'
for filename in os.listdir(folder):
if filename.endswith('.txt'):
os.unlink(os.path.join(folder, filename))

How do I make the current folder path to work for my command

I'm new to Python and really want this command to work so I have been looking around on google but I still can't find any solution. I'm trying to make a script that deletes a folder inside the folder my Blender game are inside so i have been trying out those commands:
import shutil
from bge import logic
path = bge.logic.expandPath("//")
shutil.rmtree.path+("/killme") # remove dir and all contains
The Folder i want to delete is called "killme" and I know you can just do: shutil.rmtree(Path)
but I want the path to start at the folder that the game is in and not the full C:/programs/blabla/blabla/test/killme path.
Happy if someone could explain.
I think you are using shutil.rmtree command in wrong way. You may use the following.
shutil.rmtree(path+"/killme")
Look at the reference https://docs.python.org/3/library/shutil.html#shutil.rmtree
Syntax: shutil.rmtree(path, ignore_errors=False, onerror=None)
Assuming that your current project directory is 'test'. Then, your code will look like the follwing:
import shutil
from bge import logic
path = os.getcwd() # C:/programs/blabla/blabla/test/
shutil.rmtree(path+"/killme") # remove dir and all contains
NOTE: It will fail if the files are read only in the folder.
Hope it helps!
What you could do is set a base path like
basePath = "/bla_bla/"
and then append the path and use something like:
shutil.rmtree(basePath+yourGamePath)
If you are executing the python as a standalone script that is inside the desired folder, you can do the following:
#!/usr/bin/env_python
import os
cwd = os.getcwd()
shutil.rmtree(cwd)
Hope my answer was helpful
The best thing you could do is use the os library.
Then with the os.path function you can list all the directories and filenames and hence can delete/modify the required folders while extractring the name of folders in the same way you want.
for root, dirnames, files in os.walk("issues"):
for name in dirnames:
for filename in files:
*what you want*

how to get name of a file in directory using python

There is an mkv file in a folder named "export". What I want to do is to make a python script which fetches the file name from that export folder.
Let's say the folder is at "C:\Users\UserName\Desktop\New_folder\export".
How do I fetch the name?
I tried using this os.path.basename and os.path.splitext .. well.. didn't work out like I expected.
os.path implements some useful functions on pathnames. But it doesn't have access to the contents of the path. For that purpose, you can use os.listdir.
The following command will give you a list of the contents of the given path:
os.listdir("C:\Users\UserName\Desktop\New_folder\export")
Now, if you just want .mkv files you can use fnmatch(This module provides support for Unix shell-style wildcards) module to get your expected file names:
import fnmatch
import os
print([f for f in os.listdir("C:\Users\UserName\Desktop\New_folder\export") if fnmatch.fnmatch(f, '*.mkv')])
Also as #Padraic Cunningham mentioned as a more pythonic way for dealing with file names you can use glob module :
map(path.basename,glob.iglob(pth+"*.mkv"))
You can use glob:
from glob import glob
pth ="C:/Users/UserName/Desktop/New_folder/export/"
print(glob(pth+"*.mkv"))
path+"*.mkv" will match all the files ending with .mkv.
To just get the basenames you can use map or a list comp with iglob:
from glob import iglob
print(list(map(path.basename,iglob(pth+"*.mkv"))))
print([path.basename(f) for f in iglob(pth+"*.mkv")])
iglob returns an iterator so you don't build a list for no reason.
I assume you're basically asking how to list files in a given directory. What you want is:
import os
print os.listdir("""C:\Users\UserName\Desktop\New_folder\export""")
If there's multiple files and you want the one(s) that have a .mkv end you could do:
import os
files = os.listdir("""C:\Users\UserName\Desktop\New_folder\export""")
mkv_files = [_ for _ in files if _[-4:] == ".mkv"]
print mkv_files
If you are searching for recursive folder search, this method will help you to get filename using os.walk, also you can get those file's path and directory using this below code.
import os, fnmatch
for path, dirs, files in os.walk(os.path.abspath(r"C:/Users/UserName/Desktop/New_folder/export/")):
for filename in fnmatch.filter(files, "*.mkv"):
print(filename)
You can use glob
import glob
for file in glob.glob('C:\Users\UserName\Desktop\New_folder\export\*.mkv'):
print(str(file).split('\')[-1])
This will list out all the files having extention .mkv as
file.mkv, file2.mkv and so on.
From os.walk you can read file paths as a list
files = [ file_path for _, _, file_path in os.walk(DIRECTORY_PATH)]
for file_name in files[0]: #note that it has list of lists
print(file_name)

Python open a file in a subdirectory - linux

Is it possible to open a file for reading in a sub directory without having to use os.listdir()? Something like this maybe?
f1 = open('/SCRIPT/PYTHON/monomer-b/{}'.format(xyzfile)).read()
I am running the python script in /SCRIPT/PYTHON the files that I want to call is in /SCRIPT/PYTHON/monor-b. Any suggestions
You can use relative paths while opening files in python:
import os
file_content = open(os.path.join('./monomer-b', xyzfile)).read()
Also, by default all paths looks up starting at current directory, so the './' part of subdir name is not necessary. Using os.path.join is better practice than string concatenation or formatting, because it use correct path separators and another OS-specific things.

How to move a file in Python?

How can I do the equivalent of mv in Python?
mv "path/to/current/file.foo" "path/to/new/destination/for/file.foo"
os.rename(), os.replace(), or shutil.move()
All employ the same syntax:
import os
import shutil
os.rename("path/to/current/file.foo", "path/to/new/destination/for/file.foo")
os.replace("path/to/current/file.foo", "path/to/new/destination/for/file.foo")
shutil.move("path/to/current/file.foo", "path/to/new/destination/for/file.foo")
The filename ("file.foo") must be included in both the source and destination arguments. If it differs between the two, the file will be renamed as well as moved.
The directory within which the new file is being created must already exist.
On Windows, a file with that name must not exist or an exception will be raised, but os.replace() will silently replace a file even in that occurrence.
shutil.move simply calls os.rename in most cases. However, if the destination is on a different disk than the source, it will instead copy and then delete the source file.
Although os.rename() and shutil.move() will both rename files, the command that is closest to the Unix mv command is shutil.move(). The difference is that os.rename() doesn't work if the source and destination are on different disks, while shutil.move() is files disk agnostic.
After Python 3.4, you can also use pathlib's class Path to move file.
from pathlib import Path
Path("path/to/current/file.foo").rename("path/to/new/destination/for/file.foo")
https://docs.python.org/3.4/library/pathlib.html#pathlib.Path.rename
For either the os.rename or shutil.move you will need to import the module.
No * character is necessary to get all the files moved.
We have a folder at /opt/awesome called source with one file named awesome.txt.
in /opt/awesome
○ → ls
source
○ → ls source
awesome.txt
python
>>> source = '/opt/awesome/source'
>>> destination = '/opt/awesome/destination'
>>> import os
>>> os.rename(source, destination)
>>> os.listdir('/opt/awesome')
['destination']
We used os.listdir to see that the folder name in fact changed.
Here's the shutil moving the destination back to source.
>>> import shutil
>>> source = '/opt/awesome/destination'
>>> destination = '/opt/awesome/source'
>>> shutil.move(source, destination)
>>> os.listdir('/opt/awesome/source')
['awesome.txt']
This time I checked inside the source folder to be sure the awesome.txt file I created exists. It is there
Now we have moved a folder and its files from a source to a destination and back again.
This is what I'm using at the moment:
import os, shutil
path = "/volume1/Users/Transfer/"
moveto = "/volume1/Users/Drive_Transfer/"
files = os.listdir(path)
files.sort()
for f in files:
src = path+f
dst = moveto+f
shutil.move(src,dst)
You can also turn this into a function, that accepts a source and destination directory, making the destination folder if it doesn't exist, and moves the files. Also allows for filtering of the src files, for example if you only want to move images, then you use the pattern '*.jpg', by default, it moves everything in the directory
import os, shutil, pathlib, fnmatch
def move_dir(src: str, dst: str, pattern: str = '*'):
if not os.path.isdir(dst):
pathlib.Path(dst).mkdir(parents=True, exist_ok=True)
for f in fnmatch.filter(os.listdir(src), pattern):
shutil.move(os.path.join(src, f), os.path.join(dst, f))
The accepted answer is not the right one, because the question is not about renaming a file into a file, but moving many files into a directory. shutil.move will do the work, but for this purpose os.rename is useless (as stated on comments) because destination must have an explicit file name.
Since you don't care about the return value, you can do
import os
os.system("mv src/* dest/")
Also possible with using subprocess.run() method.
python:
>>> import subprocess
>>> new = "/path/to/destination"
>>> old = "/path/to/new/destination"
>>> process = "mv ..{} ..{}".format(old,new)
>>> subprocess.run(process, shell=True) # do not remember, assign shell value to True.
This will work fine when working on Linux. Windows probably gives error since there is no mv Command.
Based on the answer described here, using subprocess is another option.
Something like this:
subprocess.call("mv %s %s" % (source_files, destination_folder), shell=True)
I am curious to know the pro's and con's of this method compared to shutil. Since in my case I am already using subprocess for other reasons and it seems to work I am inclined to stick with it.
This is dependent on the shell you are running your script in. The mv command is for most Linux shells (bash, sh, etc.), but would also work in a terminal like Git Bash on Windows. For other terminals you would have to change mv to an alternate command.
This is solution, which does not enables shell using mv.
from subprocess import Popen, PIPE, STDOUT
source = "path/to/current/file.foo",
destination = "path/to/new/destination/for/file.foo"
p = Popen(["mv", "-v", source, destination], stdout=PIPE, stderr=STDOUT)
output, _ = p.communicate()
output = output.strip().decode("utf-8")
if p.returncode:
print(f"E: {output}")
else:
print(output)
import os,shutil
current_path = "" ## source path
new_path = "" ## destination path
os.chdir(current_path)
for files in os.listdir():
os.rename(files, new_path+'{}'.format(f))
shutil.move(files, new_path+'{}'.format(f)) ## to move files from
different disk ex. C: --> D:

Categories

Resources