I have this code that searches all the files from the given directory, but I want to change it so that it can search a file from the users input? and then ask again if the file is not found? The following code i have is:
import os
import sys
from stat import *
def depthsearch(directory):
for files in os.listdir(directory):
fileItem = os.path.join(directory, files)
fileItemStatInfo = os.stat(fileItem)
if S_ISDIR(fileItemStatInfo.st_mode):
depthsearch(fileItem)
elif S_ISREG(fileItemStatInfo.st_mode):
print("Found File:", fileItem)
depthsearch("C:")
What about
depthsearch(raw_input()) # or 'input()' for Python 3
To check if a given string represents a valid directory, you can use os.path.isdir(). So you could wrap your call to depthsearch() in a while loop that keeps asking the user for input until they provide a valid directory.
You can get input by using:
Python 2.X's raw_input function:
s = raw_input()
Python 3.X's input function:
s = input()
def depthsearch(directory, fileName):
for files in os.listdir(directory):
fileItem = os.path.join(directory, files)
fileItemStatInfo = os.stat(fileItem)
if S_ISDIR(fileItemStatInfo.st_mode):
depthsearch(fileItem,filename)
elif S_ISREG(fileItemStatInfo.st_mode or (files==filename):
print("Found File:", fileItem)
depthsearch("C:", "python.exe")
This allow you to search a file in a directory. It just test if the name are the same.
Related
I am struggling to fix a bug in my code. The variable (fext) is only true for the last file in a folder. So if by chance the last file is 'jpg' then my code will continue as planned. But if by chance the last file is a 'gpx' or a 'csv' then the Else error will activate even though there is a 'jpg' file in the folder.
Can somebody please help me refine my code so that this work if all file types are in the folder? I am still quite new to Python and stuck on how to proceed.
Here is my code below:
import os, string
from os.path import isfile, join
file_path = input("Enter the folder link: ")
print("")
TF = False
path_it = (os.path.join(root, filename)
for root, _, filenames in os.walk(file_path)
for filename in filenames)
for path in path_it:
fext = os.path.splitext(os.path.basename(path))[1]
fname = os.path.splitext(os.path.basename(path))[0]
while True:
file_type = input("Enter file extention (e.g. txt, wav, jpg, gpx, pdf): ")
print(file_type)
if file_type in fext:
TF = True
break
else:
print("\n*** There is no '" + file_type + "' file extension in this folder, please try again.\n")
Other code...
Thanks
A list comprehension is likely your best solution to get your desired result. This will store all the filetypes in the directory passed in a list.
fext = [os.path.splitext(os.path.basename(path))[1] for path in path_it]
fname = [os.path.splitext(os.path.basename(path))[1] for path in path_it]
But, you also need to make sure that the input file type matches the format. The above will give you (for example) ['.csv', '.pdf', '.gpx'], so you need to make sure that the format of the input is the same, in other words, not just 'csv' but '.csv' otherwise there will be no match.
The while loop can also be changed to while not TF, and once TF changes to True, the loop will be broken, instead of breaking the loop using break.
The fext and fname variables should return an iterable if you are to check against all extensions contained within the folder. Try the following list comprehensions.
fext = [os.path.splitext(os.path.basename(path))[1] for path in path_it]
fname = [os.path.splitext(os.path.basename(path))[1] for path in path_it]
I don't think that the following code is efficient enough to search for a filename in the current directory. The filename will be stored as a string, so will python be able to search a 'filename' string from the directories that are non-string?
filename = input("What would you like to name the File? ")
import os
if f"{filename}.txt" in os.getcwd():
print(True)
os.getcwd() returns the name of the directory itself, not a list of files (see https://www.tutorialspoint.com/python/os_getcwd.htm)
You want to try something like:
import os
for file in os.listdir("/mydir"):
if file == f"{filename}.txt:
print("File Found")
Also, you need to try-except statement for this code snippet. Otherwise, at the wrong file, the app will be crashed.
import os
# Getting current folder path
cmd = os.getcwd()
# getting file name from user
file_name = input('Enter file name to be search : ')
#Looping through all folder and files in the current directory
for file in os.listdir(cmd):
# compare the file name user entered with file names from current
# directory file name
if file == f"{file_name}.txt":
print("File Found")
I want to do the following:
1) Ask the user for input for a file path they wish a directory listing for.
2) Take this file path and enter the results, in a list, in a text file in the directory they input NOT the current directory.
I am very nearly there but the last step is that I can't seem to save the file to the directory the user has input only the current directory. I have set out the current code below (which works for the current directory). I have tried various variations to try and save it to the directory input by the user but to no avail - any help would be much appreciated.
CODE BELOW
import os
filenames = os.path.join(input('Please enter your file path: '))
with open ("files.txt", "w") as a:
for path, subdirs, files in os.walk(str(filenames)):
for filename in files:
f = os.path.join(path, filename)
a.write(str(f) + os.linesep)
I came across this link https://cmdlinetips.com/2012/09/three-ways-to-write-text-to-a-file-in-python/. I think your issue has something to do with you needing to provide the full path name and or the way you are using the close() method.
with open(out_filename, 'w') as out_file:
..
..
.. parsed_line
out_file.write(parsed_line)
You have to alter the with open ("files.txt", "w") as a: statement to not only include the filename, but also the path. This is where you should use os.path.join(). Id could be handy to first check the user input for existence with os.path.exists(filepath).
os.path.join(input(...)) does not really make sense for the input, since it returns a single str, so there are no separate things to be joined.
import os
filepath = input('Please enter your file path: ')
if os.path.exists(filepath):
with open (os.path.join(filepath, "files.txt"), "w") as a:
for path, subdirs, files in os.walk(filepath):
for filename in files:
f = os.path.join(path, filename)
a.write(f + os.linesep)
Notice that your file listing will always include a files.txt-entry, since the file is created before os.walk() gets the file list.
As ShadowRanger kindly points out, this LBYL (look before you leap) approach is unsafe, since the existence check could pass, although the file system is changed later while the process is running, leading to an exception.
The mentioned EAFP (it's easier to ask for forgiveness than permission) approach would use a try... except block to handle all errors.
This approach could look like this:
import os
filepath = input('Please enter your file path: ')
try:
with open (os.path.join(filepath, "files.txt"), "w") as a:
for path, subdirs, files in os.walk(filepath):
for filename in files:
f = os.path.join(path, filename)
a.write(f + os.linesep)
except:
print("Could not generate directory listing file.")
You should further refine it by catching specific exceptions. The more code is in the try block, the more errors unrelated to the directory reading and file writing are also caught and suppressed.
Move to the selected directory then do things.
Extra tip: In python 2 use raw_input to avoid special chars error like : or \ ( just use input in python 3 )
import os
filenames = raw_input('Please enter your file path: ')
if not os.path.exists(filenames):
print 'BAD PATH'
return
os.chdir(filenames)
with open ("files.txt", "w") as a:
for path, subdirs, files in os.walk('.'):
for filename in files:
f = os.path.join(path, filename)
a.write(str(f) + os.linesep)
I'm working on an online tutorial for Python, & I'm trying to go a little farther for an example problem than it calls for.
The objective is to rename all the files in a folder. My addition is to prompt the user for the folder, rather than hardcoding it.
I've tried the suggestions in Python: user input and commandline arguments, but when I run the script no prompt text is displayed.
As it stands my script looks like this:
import os
import sys
import optparse
def RName_Files():
#Get the folder to user
Fol = raw_input("Please enter the folder whose files should have numbers stripped from their name: ") #I've never run past this point
#Iterate through the files in the folder
for f in ListDir(f):
print("Current file is '" + f)
I imagine I'm misunderstanding the answers in the question I linked to, and was hoping someone could clarify the responses for me. Especially since that thread mixes 2.7 and 3.x.
Thanks!
f is undefined when you loop through it. Did you mean ListDir(Fol)? And also ListDir is undefined too.
But above all you are not calling the RName_Files function in your program, try addding RName_Files() at the end of the script.
What could work
import os
ListDir = os.listdir
def RName_Files():
#Get the folder to user
Fol = raw_input("Please enter the folder whose files should have numbers stripped from their name: ")
#Iterate through the files in the folder
for f in ListDir(Fol):
print("Current file is '" + f)
if __name__ == "__main__":
RName_Files()
You should also follow the PEP8 naming conventions for variables and function names. In python variables and functions are snake_case, while class names are CamelCase. And you can also be more clear with your names, rename_files instead of RName_Files, folder or path instead of Fol, file_name instead of f.
Which will look like this:
from os import listdir
def rename_files():
#Get the folder to user
path = raw_input("Please enter the folder whose files should have numbers stripped from their name: ")
#Iterate through the files in the folder
for file_name in listdir(path):
print("Current file is " + file_name )
# do something with file_name
if __name__ == "__main__":
rename_files()
You need to call your method
import os
import sys
import optparse
def RName_Files():
#Get the folder to user
fol = raw_input("Please enter the folder whose files should have numbers stripped from their name: ") #I've never run past this point
#Iterate through the files in the folder
for f in os.listdir(fol):
print("Current file is '" + f)
RName_Files()
The "pythonic" way to do this would be like this:
import os
import sys
import optparse
def RName_Files():
#Get the folder to user
Fol = raw_input("Please enter the folder whose files should have numbers stripped from their name: ") #I've never run past this point
#Iterate through the files in the folder
for f in ListDir(Fol):
print("Current file is '" + f)
def main():
RName_Files()
if __name__ == "__main__":
main()
Basically you defined your function using def but never actually called it. Its good practice to have a main function to call the ones you've created and to call them in this fashion.
I need to extract a file called Preview.pdf from a folder called QuickLooks inside of a zip file.
Right now my code looks a little like this:
with ZipFile(newName, 'r') as newName:
newName.extract(\QuickLooks\Preview.pdf)
newName.close()
(In this case, newName has been set equal to the full path to the zip).
It's important to note that the backslash is correct in this case because I'm on Windows.
The code doesn't work; here's the error it gives:
Traceback (most recent call last):
File "C:\Users\Asit\Documents\Evam\Python_Scripts\pageszip.py", line 18, in <module>
ZF.extract("""QuickLooks\Preview.pdf""")
File "C:\Python33\lib\zipfile.py", line 1019, in extract
member = self.getinfo(member)
File "C:\Python33\lib\zipfile.py", line 905, in getinfo
'There is no item named %r in the archive' % name)
KeyError: "There is no item named 'QuickLook/Preview.pdf' in the archive"
I'm running the Python script from inside Notepad++, and taking the output from its console.
How can I accomplish this?
Alternatively, how could I extract the whole QuickLooks folder, move out Preview.pdf, and then delete the folder and the rest of it's contents?
Just for context, here's the rest of the script. It's a script to get a PDF of a .pages file. I know there are bonified converters out there; I'm just doing this as an excercise with some sort of real-world application.
import os.path
import zipfile
from zipfile import *
import sys
file = raw_input('Enter the full path to the .pages file in question. Please note that file and directory names cannot contain any spaces.')
dir = os.path.abspath(os.path.join(file, os.pardir))
fileName, fileExtension = os.path.splitext(file)
if fileExtension == ".pages":
os.chdir(dir)
print (dir)
fileExtension = ".zip"
os.rename (file, fileName + ".zip")
newName = fileName + ".zip" #for debugging purposes
print (newName) #for debugging purposes
with ZipFile(newName, 'w') as ZF:
print("I'm about to list names!")
print(ZF.namelist()) #for debugging purposes
ZF.extract("QuickLook/Preview.pdf")
os.rename('Preview.pdf', fileName + '.pdf')
finalPDF = fileName + ".pdf"
print ("Check out the PDF! It's located at" + dir + finalPDF + ".")
else:
print ("Sorry, this is not a valid .pages file.")
sys.exit
I'm not sure if the import of Zipfile is redundant; I read on another SO post that it was better to use from zipfile import * than import zipfile. I wasn't sure, so I used both. =)
EDIT: I've changed the code to reflect the changes suggested by Blckknght.
Here's something that seems to work. There were several issues with your code. As I mentioned in a comment, the zipfile must be opened with mode 'r' in order to read it. Another is that zip archive member names always use forward slash / characters in their path names as separators (see section 4.4.17.1 of the PKZIP Application Note). It's important to be aware that there's no way to extract a nested archive member to a different subdirectory with Python's currentzipfilemodule. You can control the root directory, but nothing below it (i.e. any subfolders within the zip).
Lastly, since it's not necessary to rename the .pages file to .zip — the filename you passZipFile() can have any extension — I removed all that from the code. However, to overcome the limitation on extracting members to a different subdirectory, I had to add code to first extract the target member to a temporary directory, and then copy that to the final destination. Afterwards, of course, this temporary folder needs to deleted. So I'm not sure the net result is much simpler...
import os.path
import shutil
import sys
import tempfile
from zipfile import ZipFile
PREVIEW_PATH = 'QuickLooks/Preview.pdf' # archive member path
pages_file = input('Enter the path to the .pages file in question: ')
#pages_file = r'C:\Stack Overflow\extract_test.pages' # hardcode for testing
pages_file = os.path.abspath(pages_file)
filename, file_extension = os.path.splitext(pages_file)
if file_extension == ".pages":
tempdir = tempfile.gettempdir()
temp_filename = os.path.join(tempdir, PREVIEW_PATH)
with ZipFile(pages_file, 'r') as zipfile:
zipfile.extract(PREVIEW_PATH, tempdir)
if not os.path.isfile(temp_filename): # extract failure?
sys.exit('unable to extract {} from {}'.format(PREVIEW_PATH, pages_file))
final_PDF = filename + '.pdf'
shutil.copy2(temp_filename, final_PDF) # copy and rename extracted file
# delete the temporary subdirectory created (along with pdf file in it)
shutil.rmtree(os.path.join(tempdir, os.path.split(PREVIEW_PATH)[0]))
print('Check out the PDF! It\'s located at "{}".'.format(final_PDF))
#view_file(final_PDF) # see Bonus below
else:
sys.exit('Sorry, that isn\'t a .pages file.')
Bonus: If you'd like to actually view the final pdf file from the script, you can add the following function and use it on the final pdf created (assuming you have a PDF viewer application installed on your system):
import subprocess
def view_file(filepath):
subprocess.Popen(filepath, shell=True).wait()