Python Forum
Very simple question about filenames and backslashes!
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Very simple question about filenames and backslashes!
#1
I have a string of a filename, that contains the entire path.

I want to remove the file extension and capture only the filename.

I have reversed the string, started from the 4th index (as all files are restricted to the same extension) and, now, only have to lose the entire path by looking for the first backslash \ and break out of the loop.

I have currently done a basic if statement:

if (letter == "\\"):
But this does not work; or the code within the if is never run.

What am I missing here?
Reply
#2
Use pathlib.

No idea what you are missing other than enough information in your post for anyone to possibly answer the question. When asking what is wrong with code, post the code, not a description of the code. For example:
full_file_name = r"C:\this\is\my\file.txt"
reversed = full_file_name[::-1][4:]
print(reversed)
for index, letter in enumerate(reversed, start=1):
    if letter == "\\":   # I don't think this works
        break
    filename = reversed[:index][::-1]
else:
    filename = ""

print(filename)
This provides context for the question and it also lets others see what really happens, not what you think is happening. Remember, there is an error somewhere. That error could as easily be your expectations or observations as it could be a programming error.

Oh, and use pathlib
ndc85430 likes this post
Reply
#3
(Jan-16-2023, 11:38 AM)garynewport Wrote: I want to remove the file extension and capture only the filename.
As mention pathlib is the best choice for this,
there is way for this in os module like basename,but pathlib is more flexible.
>>> from pathlib import Path
>>> 
>>> my_path = r'C:\my\path\to\file.txt'
>>> p = Path(my_path)
>>> p
WindowsPath('C:/my/path/to/file.txt')

>>> p.name
'file.txt'
>>> p.stem
'file'
>>> p.suffix
'.txt'
>>> p.parent
WindowsPath('C:/my/path/to')
>>> p.parts
('C:\\', 'my', 'path', 'to', 'file.txt')
garynewport and ibreeden like this post
Reply
#4
(Jan-16-2023, 03:18 PM)deanhystad Wrote: Use pathlib.

No idea what you are missing other than enough information in your post for anyone to possibly answer the question. When asking what is wrong with code, post the code, not a description of the code.

Oh, and use pathlib

Yes, sorry; I was actually trying not to overload the question and resulted in the opposite outcome. LOL

The two definitions of interest are:

    def browseFiles(self):

        fileList = ""

        filename = fd.askopenfilename(title      = "Select a File",
                                      filetypes  = (("LST files", "*.lst"),
                                                    ("all files", "*.*")))
        # Change label contents
        
        if not filename in self.filenames:
            self.findFilename(filename)
            self.filenames.append(filename)
            self.combobox.configure(state = "normal")
            self.stelcorData.append(self.readData(filename))
            for item in self.filenames:
                fileList = fileList + item + "\n"
            self.files.configure(text    = fileList,
                                 anchor  = "nw",
                                 justify = "left")


    def findFilename(self, details):
        fullpath = details[::-1]
        filename = ""
        for index, letter in enumerate(fullpath):
            
            if (index > 3):
                print(letter)
                if (letter == "\\"):
                    break
                filename = filename + letter
        print(filename[::-1])
It is within the findFilename definition that I have the issue. The filenames can be in many forms (since this runs on Windows, Macs and Linux systems), but can be a long path. The main fact is that the first backslash that will be encountered also denotes the end of the path and the beginning of the filename.

I will have a read of pathlib in a moment. Though another posted an example I couldn't see how I would utilise this, in the short glance I was able to give it.

UPDATE: Another glance makes pathlib very interesting; thank you. Smile
UPDATE TO UPDATE: Solved! Thank you so much both of you.
Reply
#5
If it can run on anything, using backslash is a bad idea. If you are running this on Mac or Linux, looking for '\\' is guaranteed to fail.

When posting code, post the least amount of code needed to demonstrate the problem. I would make a copy of the code and start removing things. My first pass would look like this:
def findFilename(details):
    fullpath = details[::-1]
    filename = ""
    for index, letter in enumerate(fullpath):
        if index > 3:
            print(letter)
            if letter == "\\":
                break
            filename = filename + letter
    print(filename[::-1])


filename = r"C:\this\is\a\test.txt"
findFilename(filename)
print(filename)
Output:
t s e t \ test C:\this\is\a\test.txt
This would demonstrate that the findFilename function kind of works, but it doesn't change the value of "filename". "filename" inside findFilename() is not the same as filename outside the function. These are two completely different variables that just happen to have the same hame. You would search for this problem online and learn that using variables to return values from a function is a bad idea, You should use the return statement.

That would lead to my second attempt.
def findFilename(details):
    fullpath = details[::-1]
    filename = ""
    for index, letter in enumerate(fullpath):
        if index > 3:
            if letter == "\\":
                break
            filename = filename + letter
    return filename[::-1]


filename = findFilename(r"C:\this\is\a\test.txt")
print(filename)
Output:
test
That appears to work, so next I might write some quick and dirty tests,
def findFilename(details):
    fullpath = details[::-1]
    filename = ""
    for index, letter in enumerate(fullpath):

        if index > 3:
            if letter == "\\":
                break
            filename = filename + letter
    return filename[::-1]



assert findFilename(r"C:\this\is\a\test.txt") == "test"
assert findFilename(r"C:\test.txt") == "test"
assert findFilename(r"C:\test") == "test"
Error:
line 15, in <module> assert findFilename(r"C:\test") == "test" AssertionError
This points out that my code is sensitive to the length of the extension. If I select a file without a three letter extension, it fails.

I think about other ways my code might fail. I write better tests using unittest.

import unittest


def findFilename(details):
    fullpath = details[::-1]
    filename = ""
    for index, letter in enumerate(fullpath):

        if index > 3:
            if letter == "\\":
                break
            filename = filename + letter
    return filename[::-1]


class TestFindFilename(unittest.TestCase):
    def test_normal(self):
        self.assertEqual(findFilename(r"C:\this\isa\test.txt"), "test")

    def test_no_path(self):
        self.assertEqual(findFilename(r"test.txt"), "test")

    def test_no_extension(self):
        self.assertEqual(findFilename(r"C:\test"), "test")

    def test_long_extension(self):
        self.assertEqual(findFilename(r"C:\test.text"), "test")

    def test_short_extension(self):
        self.assertEqual(findFilename(r"C:\test.text"), "tt")

    def test_slashes(self):
        self.assertEqual(findFilename("/this/isa/test.txt"), "test")


if __name__ == "__main__":
    unittest.main()
Output:
====================================================================== FAIL: test_long_extension (__main__.TestFindFilename) ---------------------------------------------------------------------- Traceback (most recent call last): File "c:\Users\hystadd\Documents\python\sandbox\junk2.py", line 27, in test_long_extension self.assertEqual(findFilename(r"C:\test.text"), "test") AssertionError: 'test.' != 'test' - test. ? - + test ====================================================================== FAIL: test_no_extension (__main__.TestFindFilename) ---------------------------------------------------------------------- Traceback (most recent call last): File "c:\Users\hystadd\Documents\python\sandbox\junk2.py", line 24, in test_no_extension self.assertEqual(findFilename(r"C:\test"), "test") AssertionError: '' != 'test' + test ====================================================================== FAIL: test_short_extension (__main__.TestFindFilename) ---------------------------------------------------------------------- Traceback (most recent call last): File "c:\Users\hystadd\Documents\python\sandbox\junk2.py", line 30, in test_short_extension self.assertEqual(findFilename(r"C:\testtt"), "test") AssertionError: 'tes' != 'test' - test. + tt ====================================================================== FAIL: test_slashes (__main__.TestFindFilename) ---------------------------------------------------------------------- Traceback (most recent call last): File "c:\Users\hystadd\Documents\python\sandbox\junk2.py", line 33, in test_slashes self.assertEqual(findFilename("/this/isa/test.txt"), "test") AssertionError: '/this/isa/test' != 'test' - /this/isa/test + test ---------------------------------------------------------------------- Ran 6 tests in 0.003s FAILED (failures=4)
Only 2 tests passed! I have a problem with short, long, or missing extensions. I also have a problem with slash vs backslash. I think linux uses slash, so this is a problem if I want to run on linux.

While learning about unit test and reading posts about getting just the filename without path or extension, I saw pathlib mentioned. I read up on pathlib and it sounds like it does what I need. I write a new version of my function that uses pathlib.
from pathlib import Path
import unittest


def findFilename(filedescr):
    return Path(filedescr).stem


class TestFindFilename(unittest.TestCase):
    def test_normal(self):
        self.assertEqual(findFilename(r"C:\this\isa\test.txt"), "test")

    def test_no_path(self):
        self.assertEqual(findFilename(r"test.txt"), "test")

    def test_no_extension(self):
        self.assertEqual(findFilename(r"C:\test"), "test")

    def test_long_extension(self):
        self.assertEqual(findFilename(r"C:\test.text"), "test")

    def test_short_extension(self):
        self.assertEqual(findFilename(r"C:\test.tt"), "test")

    def test_slashes(self):
        self.assertEqual(findFilename("/this/isa/test.txt"), "test")


if __name__ == "__main__":
    unittest.main()
Output:
...... ---------------------------------------------------------------------- Ran 6 tests in 0.001s OK
All 6 tests pass!

Since my function is only 1 line long, I question whether I need the function at all. I modify my program to use pathlib instead of writing my own functions that I need to test and maintain.
ndc85430 likes this post
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Next/Prev file without loading all filenames WilliamKappler 9 469 Apr-12-2024, 05:13 AM
Last Post: Pedroski55
  Very Beginner question on simple variables Harvy 1 169 Apr-12-2024, 12:03 AM
Last Post: deanhystad
  Simple Question - ' defined as "a". ?' Ryan012 10 1,606 May-27-2023, 06:03 PM
Last Post: Ryan012
  Python Tkinter Simple Multithreading Question AaronCatolico1 5 1,563 Dec-14-2022, 11:35 PM
Last Post: deanhystad
  A simple "If...Else" question from a beginner Serena2022 6 1,700 Jul-11-2022, 05:59 AM
Last Post: Serena2022
  select Eof extension files based on text list of filenames with if condition RolanRoll 1 1,509 Apr-04-2022, 09:29 PM
Last Post: Larz60+
  Simple arithmetic question ebolisa 5 2,038 Dec-15-2021, 04:56 PM
Last Post: deanhystad
  Simple code question about lambda and tuples JasPyt 7 3,299 Oct-04-2021, 05:18 PM
Last Post: snippsat
Big Grin question about simple algorithm to my problem jamie_01 1 1,667 Oct-04-2021, 11:55 AM
Last Post: deanhystad
  Simple question 1234 4 2,262 Dec-04-2020, 12:29 PM
Last Post: DeaD_EyE

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020