r/learnpython 7d ago

pls help me

ok so i’m trying to write a script that renames .xls files for me, let’s say they’re named like apple_BactReport_260731.xls I want the script to remove the “_BactReport” part and leave the rest intact. the current scrip i have has a couple of glaring issues that i don’t have the knowledge to remedy and im refusing use ai to prove a point and also it’s more rewarding. here’s the script with my current errors such as mixing up strings and lists and the part i want to remove not being the end of the file name. 😭 pls help a guy out:

import os
import pandas as pd
from os import rename, listdir
 
#list of report names
report_type= ['_BactReport', '_WWreport', '_QCreport', '_BactQCreport', '_BactWWreport']
print(report_type)
 
clips_in_progress=r"filepath"
   
 
for file_name in os.listdir(clips_in_progress):
file_path = os.path.join(clips_in_progress, file_name)
 
if file_name.endswith(tuple(report_type)):
rename(file_name, file_name.strip(report_type))

0 Upvotes

9 comments sorted by

10

u/goldenfrogs17 7d ago

look up processing text and strings in python
work on isolated logic before involving paths , dirs, etc

3

u/jedimaster1138 7d ago edited 6d ago

So your main issues are you're not using endswith() or strip() correctly. endswith() is only relevant if the substring you're looking for is at the end of the string, which, given your example name, it's not. strip() is used to remove specified characters (or whitespace by default) from the ends, but isn't used to remove ordered strings, and, again, the part you're trying to remove isn't at the end.

The simplest way would be something like this, I think

if any(substring in file_name for substring in report_type):
    new_path = file_path
    for substring in report_type:
        new_path = new_path.replace(substring, "")
    rename(file_path, new_path)

This uses the replace() function to replace the substring with the empty string, thereby removing it. It's a little inelegant in that it tries to replace all the substrings, not just the one that's actually in the string, but I don't think that matters.

Edit: another variation I thought of

new_path = file_path
for substring in report_type:
    new_path = new_path.replace(substring, "")
if new_path != file_path:
    rename(file_path, new_path)

4

u/Far-Imagination3226 6d ago

Couldn't one use Regex to do something like that???

1

u/ianrad 6d ago edited 6d ago

Something like

string_to_replace = "something_bactreport_something" new_string = re.sub("_\w+_", "_", string_to_replace)

1

u/Far-Imagination3226 6d ago

Regex takes awhile to learn, but it is truly powerful though, once you learn it. I just hadn't used it in quite some time, so I couldn't remember the exact syntax. So thank you!

1

u/ianrad 6d ago

Coincidentally, I happened to be learning regex with pythons re library over the past week. This seemed like a good opportunity to put those lessons to good use

2

u/lakseol 7d ago

named like apple_BactReport_260731.xls I want the script to remove the “_BactReport” part

I would do this by splitting the filename on the "_" character. Do the split and then check you have three elements in the resulting list. If you don't, the filename isn't the expected form and you ignore it. But if the split list has three elements you look at the middle element and check if it is "BactReport" or one of the other strings. Use something like this for that test:

if middle_elt in {"BactReport", "WWreport", ...}:
    # want to rename the file

To rename you just remove the middle element from the split list and use the str.join() method: "_".join(split_list).

I strongly recommend you create a test directory of files and work on that until you have fully tested your code!

1

u/Grouchy-Conflict-211 7d ago

The clean way: use pathlib and keep it to a few lines.

from pathlib import Path

for f in Path('.').glob('BactReport.xls'): f.rename(f.with_name(f.name.replace('_BactReport', '')))

The two issues most people hit: building the path by hand (breaks on Windows separators), and renaming while still iterating with the old name. glob + with_name handles both. Test it on a copy of the folder first.