RRSC
RRSC

Reputation: 257

Get file details (complete file path) from the filename (only basename) existing as a text in tkinter Text widget

With the help of following code I am inserting the filename (file basename) in the tkinter Text widget and subsequently then trying to print the complete file path after the "Get Data" button is pressed.

import tkinter as tk
from tkinter.filedialog import askopenfilename
import os

root=tk.Tk()    

ent=tk.Text(root)
ent.grid(row=1,column=0)

def addfile():
    filename =askopenfilename(filetypes=(("Tiff files","*.tif"),("All files","*.*")))
    ent.insert(tk.INSERT, '"' + os.path.basename(filename) + '"') 
    ent.insert(tk.INSERT, "\n")

def getfile():
    print(ent.get("1.0", tk.END))

b=tk.Button(root,text="Select File",command=addfile)
b.grid(row=0,column=0)

b1 = tk.Button(root,text="Get Data",command=getfile)
b1.grid(row=2,column=0)

root.mainloop()

After running the above code only filenames are getting printed (without filepath).

Now basically what I want is that, after the "Get Data" button is pressed (where the contents of Text widget is read) then complete path of files should be printed.

Additional information:-

I know that if filenames would have been different then I could have used dictionary (key, value) pair to link basename of each file with its absolute path. But issue will come when different files present in different folder location but having same names are added to the Text widget.

Upvotes: 0

Views: 186

Answers (2)

MrRBM97
MrRBM97

Reputation: 169

I will split my code up to try and explain what i've done.

The first 4 functions are to do the addfile(): plus the other thing you have asked for.

  1. The first function split_filename(path): does what the fuction name says. It will take the path entered and create a list of the individual parts of the the path. (i.e. if you have D:/folder/example/help/test.tif it would return ['D:/', 'folder', 'example', 'help', 'test.tif'], you will see later that this is useful when you have 2 basenames that are the same.
def split_filename(path):
    allParts = []
    while 1:
        parts = os.path.split(path)
        if parts[0] == path:
            allParts.insert(0, parts[0])
            break
        elif parts[1] == path:
            allParts.insert(0, parts[1])
            break
        else:
            path = parts[0]
            allParts.insert(0, parts[1])
    return allParts
  1. check_if_fileBasename_in_current_content(current_content, selected_file_basename): again the function name tells you exactly what is does. This checks if the new selected file basename is already in the Text widget.
def check_if_fileBasename_in_current_content(current_content, selected_file_basename):
    for line in current_content:
        if line == '':
            pass
        elif line == selected_file_basename:
            return True
  1. The third if_true_split_path_for_basename(selected_file_path, selected_file_basename): is called if the new selected file basename already exists in the Text widget. The fuction takes the path for both the new selected file and the 1 already saved. If you have 2 files: D:/example1/help.tif(new selected) and D:/example2/help.tif(previously added) the new selected basename would become example2/help.tif instead of just help.tif. By doing this it makes it possible to distiquish the difference between the 2 files. At the end of the fuction the basename created thought the fuction is inserted into ent and added to the dictionary dict_of_filenames(this become useful when printing the paths when b1 is clicked.)
def if_true_split_path_for_baseline(selected_file_path, selected_file_basename):
    basename_for_text_widget = []
    if selected_file_path in dict_of_filenames:
        pass
    else:
        for path, basename in dict_of_filenames.items():
            if basename == selected_file_basename:
                duplicate_path_split = split_filename(path)
                selected_file_path_split = split_filename(selected_file_path)
                for i in range(len(selected_file_path_split)):
                    duplicate_slice = duplicate_path_split[-(i + 1)]
                    selected_slice = selected_file_path_split[-(i + 1)]
                    if duplicate_slice == selected_slice:
                        basename_for_text_widget.insert(0, selected_slice)
                    else:
                        basename_for_text_widget.insert(0, selected_slice)
                        break

        ent.insert(tk.INSERT, str('/'.join(basename_for_text_widget) + '\n'))
        dict_of_filenames.update({selected_file_path: '/'.join(basename_for_text_widget)})
  1. addFile() link all of the functions above, it: ask for a file; get the basename; get all of the current text is in the Text widget; checks if the basename already exists and if so call fuction 3 (above), and finally if it is a new basename it inserts the basename to ent and adds both path and basename to the dictionary.
def addFile():
    selected_file_path = askopenfilename(filetypes=(("Tiff files", "*.tif"), ("All files", "*.*")))
    selected_file_basename = os.path.basename(selected_file_path)
    current_content = ent.get("1.0", tk.END).splitlines()

    check1 = check_if_fileBasename_in_current_content(current_content, selected_file_basename)
    basename_for_text_widget = []
    if check1:
        if_true_split_path_for_baseline(selected_file_path, selected_file_basename)

    else:
        basename_for_text_widget.append(selected_file_basename)
        dict_of_filenames.update({selected_file_path: ''.join(basename_for_text_widget)})
        ent.insert(tk.INSERT, str(' '.join(basename_for_text_widget) + '\n'))

Next is the getFile(): takes the the content of ent and then takes the basename and prints the corresponding path.

def getFile():
    current_content = ent.get(1.0, tk.END).splitlines()
    for path, basename in dict_of_filenames.items():
        if basename in current_content:
            print(path)

The final change you need to do is to create the global dictionary by adding dict_of_filename = {} Insert below the def getFile(): fuction, with no indentation like the Text and Button variables

Everything else stays as is.

Upvotes: 0

MrRBM97
MrRBM97

Reputation: 169

As Cool Cloud has commented it is hard to give the exact answer you need, because you havent told us what is happening and what you expect/what to happen.

The way I read it is that you either want:

  1. the whole filename, which you have recieved from the askopenfilename() to be inserted in the Text widget.
  2. you want the whole filename to be printed when you click the Button b1, but the Text widget to be left as is.

1. I would change def addfile(): to

def addfile():
    filename = askopenfilename()
    ent.insert(tk.INSERT, '"' + filename + '"\n')

What this does is inserts the full file path rather than just the basename, i.e. it would insert "D:/example/help.tif" rather than just help.tif.

2. I would use the code below

root = tk.Tk()

def addfile():
    filename = askopenfilename()
    list_of_filenames.append(filename)
    ent.insert(tk.INSERT, '"' + os.path.basename(filename) + '"\n') 

def getfile():
    for i in range(len(list_of_filenames)):
        print(list_of_filesnames[i])
                   

list_of_filenames = []

ent = tk.Text(root)
ent.grid(row=1, column=0)

b=tk.Button(root,text="Select File",command=addfile)
b.grid(row=0,column=0)

b1 = tk.Button(root,text="Get Data",command=getfile)
b1.grid(row=2,column=0)

root.mainloop()

What I have done is create a global list variable named list_of_filenames and in def addfile(): I added the line list_of_filenames.append(filename), this takes the file you selected, and the path, and add it to the list variable. Thus giving you a list with every file you select, and it can be accessed by any function you build because it is global.

The final change is to def getfile(): this can be done exactly how you would like to, I have written it to print each of the files individually on a seperate lines, without square brackets or quotation marks.

Using the same example as in part 1, if I selected a file with the path D:/example/help.tif the Text widget would read "help.tif" and when b1 is clicked D:/example/help.tif would be printed to the consol.

Upvotes: 1

Related Questions