Changing many filenames using slightly differing prefixes - python

I'm trying to change a lot of file names at once but have run into a problem I can not figure out. I have a list of filenames that all start with "#### - "
i.e. "1942 - testfile001.txt"
all files start with a "yyyy - " a four digit year, a space, a dash, and a space ...
I want to remove all of this "yyyy - " and keep the rest
#!/usr/bin/env python
from os import rename, listdir
badprefix = "1942 - "
fnames = listdir('H:/testing/1928-1949/')
for fname in fnames:
if fname.startswith(badprefix):
rename(fname, fname.replace(badprefix, '', 1))
When I use the specific text above, badprefix = "1942 - ", it works for only files that of course start with 1942
any time I try to throw in a wildcard (#,*,?), badprefix = "19## - " or badprefix = "19?? - " it doesn't work.
My questions are:
In the badprefix variable, what would I use so that any and all files that start with "#### - " are included?
What should I be reading to understand what I am doing wrong?

Would this code solve your problem?
import os, glob
path = "/tmp/test/"
files = "*.txt"
dummy_year = "1234 - "
for oldpath in glob.glob(path + files):
newpath = path + oldpath[len(path)+len(dummy_year):]
print("from: ", oldpath, "to:", newpath)
os.rename(oldpath, newpath)
It renames
1234 - cdef abc sdf.txt
1946 - abcde sdf.txt
to
abcde sdf.txt
cdef abc sdf.txt

Related

'unexpected indent' in python

I am making a program in python where I read a filepath, put different pieces of that path in variables, change the path and make a new dir with that path. Everything almost seems to work. But at the end when I try to create the new dirs I am getting 'unexpected indent' error on
newFilePath.mkdir(parents=True)
I can't seem to find the problem.
import os
import shutil
from pathlib import Path
root = "C:\Voorleessoftware\\"
path = os.path.join(root, "targetdirectory")
for path, subdirs, files in os.walk(root):
for name in files:
filePath = str(os.path.join(path, name))
#filepath voorbeeld = c:\Voorleessoftware\1 sept\10u30\1e graad\1A1\test.txt
findchar1 = '\\'
list = [pos for pos, char in enumerate(filePath) if char == findchar1]
rootDir = filePath[0:list[0]]
standaard = filePath[list[0]:list[1]]
dag = filePath[list[1]:list[2]]
uur = filePath[list[2]:list[3]]
graad = filePath[list[3]:list[4]]
klas = filePath[list[4]:list[5]]
bestand = filePath[list[5]:len(filePath)-1]
#nieuwe filepath
newFilePath = rootDir + standaard + dag + graad + klas + uur + bestand
# Dirs aanmaken nieuw filepath
newFilePath.mkdir(parents=True)
Thanks in advance
You have no indentation between
newFilePath = rootDir + standaard + dag + graad + klas + uur + bestand
and
# Dirs aanmaken nieuw filepath
newFilePath.mkdir(parents=True)
Which means your two for blocks are interpreted as ending after the former, which in turn means that your indentations for the last line are unexpected. To see the difference, try marking (with your cursor) the empty line before the #nieuwe filepath, and then also the empty line before the # Dirs aanmaken nieuw filepath – you'll see the difference.
it should be either this
root = "C:\Voorleessoftware\"
or this root = "C:\\Voorleessoftware\\"
always use \\ to represent path in windows
thank you

Sorting corresponding files into the same directory

I've got 6 directories (A, B, C, D, E, F) containing .mov files.
The structure is:
A
-0001_01.mov
-0002_01.mov
-...
B
-0001_02.mov
-0002_02.mov
-...
And so on.
First, I want to create as many directories as there are files in one of the directories mentioned above.
Let's say A contains 35 .mov files (B, C .. contain the same amount of .mov files).
I now got 35 folders starting from "01" up to "35".
Now I want to copy each corresponding .mov file into the same directory, which means 0001_01.mov - 0001_06.mov go into "01", 0002_01.mov - 0002_06.mov go into "02" and so on.
I've got the creation of the directories working, but I just can't wrap my head around the copying part.
import os
pathA = ("./A/")
pathB = ("./B/")
pathC = ("./C/")
pathD = ("./D/")
pathE = ("./E/")
pathF = ("./F/")
path, dirs, filesA = next(os.walk(pathA))
file_countA = len(filesA)
path, dirs, filesB = next(os.walk(pathB))
file_countB = len(filesB)
path, dirs, filesC = next(os.walk(pathC))
file_countC = len(filesC)
path, dirs, filesD = next(os.walk(pathD))
file_countD = len(filesD)
path, dirs, filesE = next(os.walk(pathE))
file_countE = len(filesE)
path, dirs, filesF = next(os.walk(pathF))
file_countF = len(filesF)
path2 = ("./")
if file_countA == file_countB == file_countC == file_countD == file_countE == file_countF:
print("true")
else:
print ("false")
for i in range(file_countA):
try:
if i < 9:
os.mkdir(path2 + "0" + str(i + 1))
path3 = ("./" + "0" + str(i + 1))
print (path3)
elif i >= 9:
os.mkdir(path2 + str(i + 1))
path3 = ("./" + str(i + 1))
print (path3)
except OSError:
print ("Creation of the directory %s failed" % path2)
else:
print ("Successfully created the directory %s " % path2)
This is my first time using python, I think the code reflects that.
I've now wasted countless hours on this, so any help is appreciated.
So I changed your code quite a bit and tested it quickly on my system and it seemed to do what you wanted. Can you try and let me know if this gave you idea of how it can be done?
Disclaimer: I'm not Python expert by any means but I find my way around it and this is most likely not the prettiest solution but it deos work on my machine exactly as you wanted it. Just make sure you run it from inside your folder and if you are not running it from outside your folder then change cwd = os.getcwd() to cwd = "path-to-your-folder"
import os
import shutil
import glob
paths = ["/A/","/B/","/C/","/D/","/E/","/F/"]
cwd = os.getcwd()
num_folders = 0
for path in paths:
num_files = len([f for f in os.listdir(cwd+path)if os.path.isfile(os.path.join(cwd+path, f))])
if num_files>num_folders:
num_folders = num_files
for i in range(num_folders):
try:
if i < 9:
fname = cwd + "/0" + str(i + 1)
os.mkdir(fname)
for path in paths:
source = cwd + "/" + path
filename = "000{}_*.mov".format(i+1)
for file in glob.glob(os.path.join(source,filename)):
shutil.copy2(file,fname)
elif i >= 9:
fname = cwd + "/" + str(i + 1)
os.mkdir(fname)
for path in paths:
source = cwd + "/" + path
filename = "00{}_*.mov".format(i+1)
for file in glob.glob(os.path.join(source,filename)):
shutil.copy2(file,fname)
except OSError:
pass
I'm no python expert either (look at my scores too, hi), but I've tried to keep your original coding order as much as possible. I would recommend to look at different codes for real expert-tier code but it seems to do what you're asking for :
import os
import shutil
mov_pathes = ["./a/", "./b/"]
all_files = []
lengths = []
for mov_path in mov_pathes :
# listdir gives you all files in the direcetory
files_in_dir = os.listdir(mov_path)
# we'll save those in a list along with where it's from ,
# ex : ('./patha/',['0001_01.mov','0002_01.mov'])
all_files.append((mov_path, files_in_dir))
# also length info for "all items are equal length" comparison in the future
lengths.append(len(files_in_dir))
if lengths.count(lengths[0]) == len(lengths) :
print ("true")
else :
print ("false")
base_dir = "./"
for i in range (1,lengths[0]+1) :
try :
# zfill(n) fills rest of your string to 0, (ex. "7".zfill(5) gives you 00007), probably helpful for future
path_name = base_dir + str(i).zfill(2)
os.mkdir(path_name)
except OSError :
print ("Creation of the directory {path_name} failed".format(path_name = path_name))
else :
print ("Successfully created the directory {path_name}".format(path_name = path_name))
Does exactly the same thing but it would probably make maintaining your code easier laster on.
for your real question, IF we're sure that your inputs are gonna look like 00XX_NN.mov, adding
for files in all_files :
# Remember we saved as (original dir, list of files in the dir?)
# This is a original dir
source_dir = files[0]
# This is list of files in that directory
source_files = files[1]
for file in source_files :
# so original file is located in source_dir + file
source_file = source_dir + file
# and your target directory is 00XX, so getting file[2:4] gives the target directory
target_dir = base_dir + file[2:4]
#shutil.copy (source file, target directory) copies your files.
shutil.copy (source_file , target_dir)
seems to do what you're asking for, at least for me. Once again I'm no expert so let me know if it's not working!
tested with :
./a
- 0001_01
- 0002_01
- 0003_01
./b
- 0001_02
- 0002_02
- 0003_02
result :
./01 :
- 0001_01
- 0001_02
./02 :
- 0002_01
- 0002_02
./03 :
- 0003_01
- 0003_02

How to move and rename multiple files to a specific folder?

I have a small problem with a tool I built in Python.
This tool works classifying files by filenames and making folders by a word in every filename and then moving all the files to the corresponding folder.
Files:
09052019_6_filetype1_currenttime_randomnumber.xml
09052019_2_filetype2_currenttime_randomnumber.xml
09052019_9_filetype3_currenttime_randomnumber.xml
09052019_1_filetype3_currenttime_randomnumber.xml
09052019_1_filetype3_currenttime_randomnumber.xml
Actual results:
filetype1_Status_6(folder)
09052019_6_filetype1_currenttime_randomnumber.xml
filetype2_Status_2(folder)
09052019_2_filetype2_currenttime_randomnumber.xml
filetype3_Status_9(folder)
09052019_9_filetype3_currenttime_randomnumber.xml
filetype3_Status_1(folder)
09052019_1_filetype3_currenttime_randomnumber.xml
09052019_1_filetype3_currenttime_randomnumber.xml
Code Version 1.0
#!/usr/bin/python3
# v1.0
# Importing modules
import os
import shutil
import sys
# Path of input and output files
src = input('Input files: ')
dest = input('Destination files: ')
os.chdir(dest)
def classify():
for f in os.listdir(src):
splitname = f.split('_')
status = splitname[1]
topic = splitname[2]
foldername = topic + '_' + 'Status_' + status
if not os.path.exists(foldername):
os.mkdir(foldername)
shutil.move(os.path.join(src, f), foldername)
print('Sorting out files, please wait...')
classify()
print('¡DONE!')
Improvement
But in the v2.0 I would like to "improve" it a little more, just keeping the same usability but changing filenames from original name to "Message_*.xml" and it works but only moving one file, not all of them.
Current results:
filetype1_Status_6(folder)
Message_.xml
filetype2_Status_2(folder)
Message.xml
filetype3_Status_9(folder)
Message_.xml
filetype3_Status_1(folder)
Message_.xml
Expected results:
filetype1_Status_6(folder)
Message_.xml
filetype2_Status_2(folder)
Message.xml
filetype3_Status_9(folder)
Message_.xml
filetype3_Status_1(folder)
Message_.xml
Message_1.xml
Code Version 2.0
#!/usr/bin/python3
# v2.0
# Importing modules
import os
import shutil
import sys
# Path of input and output files
src = input('Input files: ')
dest = input('Destination files: ')
os.chdir(dest)
def classify():
for f in os.listdir(src):
splitname = f.split('_')
status = splitname[1]
topic = splitname[2]
foldername = topic + '_' + 'Status_' + status
newFileName = foldername + '\\' + 'Message_' + '.xml'
if not os.path.exists(foldername):
os.mkdir(foldername)
shutil.copy(os.path.join(src, f), newFileName)
print('Sorting out files, please wait...')
classify()
print('¡DONE!')
You are naming everything Message_ so you will never get multiple files. You need to parse the names in the folder and then increment the filenames accordingly.
msgName = 'Message_0'
newFileName = foldername + '\\' + msgName + '.xml'
if not os.path.exists(foldername):
os.mkdir(foldername)
else:
while os.path.isfile(newFileName) is True:
msgInt = int(msgName[8:])
msgInt += 1
msgName = msgName[:8] + str(msgInt)
newFileName = foldername + '\\' + msgName + '.xml'
shutil.copy(os.path.join(src, f), newFileName)
Now if you already have message_0.xml in your folder, you will get a message_1.xml instead, and so on.

os.rename deleting files python 3

Python novice, my simple script gets a given directory and renames all files sequentially, however it is deleting the files but the print is showing the files names getting renamed, not sure where its going wrong here.
Also, in what order does it retrieve these files?
import os
path = os.path.abspath("D:\Desktop\gp")
i = 0
for file_name in os.listdir(path):
try:
print (file_name + " - " + str(i))
os.rename(os.path.join(path,file_name), str(i))
except WindowsError:
os.remove(str(i))
os.rename(os.path.join(path,file_name), str(i))
i += 1
print(str(i) + " files.")
Edit
Below is the solution with working code, retrieves all files in a dir by creation date and assigns them a iterated number while retaining file extension.
import os
def sorted_dir(folder):
def getctime(name):
path = os.path.join(folder, name)
return os.path.getctime(path)
return sorted(os.listdir(path), key=getctime)
path = os.path.abspath("D:\Path\Here")
i = 0
for file_name in sorted_dir(path):
_, ext = os.path.splitext(file_name)
print (file_name + " - " + str(i)+ext)
os.rename(os.path.join(path,file_name), os.path.join(path, str(i) + ext))
i += 1
print(str(i-1) + " files.")
The problem is that you're using an absolute path for the source, but a relative path for the destination. So the files aren't getting deleted, they're just getting moved into the current working directory.
To fix it so they get renamed into the same directory they were already in, you can do the same thing on the destination you do on the source:
os.rename(os.path.join(path,file_name), os.path.join(path, str(i)))
From a comment, it sounds like you may want to preserve the extensions on these files. To do that:
_, ext = os.path.splitext(file_name)
os.rename(os.path.join(path,file_name), os.path.join(path, str(i) + ext))

Python code to print directories recursively

I have the following code , but it traverses the 1st directory it finds and stops.
I feel i have the recursive function which should have given the other directories too.
Can anyone please point out what is wrong with this code.
def func(path,no):
no=no+2
for item in os.listdir(path):
if os.path.isfile(path+"\\"+item):
print no * "-" + " " + item
if os.path.isdir(path+"\\"+item):
path=path + "\\" + item
print no * "-" + " " + item
func(path,no)
path="D:\\Hello"
no=0
func(pah,no)
OUTPUT :
-- 1.txt
-- 2.txt
-- 3.txt
-- blue
---- 33.txt
---- 45.txt
---- 56.txt
---- Tere
"blue" & "tere" are the directories. There are more directories int the "HELLO" folder which is not printed.
To walk through directories recursivly, use os.walk
import os
path = r'path\to\root\dir'
for root, dirs, files in os.walk(path):
# Access subdirs and files
On another note:
To join parts of a path together, use os.path.join. So instead of path+"\\"+item you could use os.path.join(path, item). This will work on all platforms, and you don't have to think about escaping slashes etc.
A better way to print values is to use the format method. In your case you could write
print '{} {}'.format(no*'-', item)`
instead of
print no * "-" + " " + item
It's because you change the path value to path + "\\" + item when you first find a directory. Then os.path.isfile(path+"\\"+item) and os.path.isdir(path+"\\"+item) all return False.
It should be like this:
def func(path,no):
no=no+2
for item in os.listdir(path):
if os.path.isfile(path+"\\"+item):
print no * "-" + " " + item
if os.path.isdir(path+"\\"+item):
print no * "-" + " " + item
func(path + "\\" + item,no)

Categories

Resources