I'm trying in vain to rewrite my old Powershell script found here - "$_.extension -eq" not working as intended? - for Python.I have no Python experience or knowledge and my 'script' is a mess but it mostly works. The only thing missing is that I would like to be able to ignore folders which don't contain 'mp3s', or whichever filetype I specify. Here is what I have so far -
import os, os.path, fnmatch
path = raw_input("Path : ")
for filename in os.listdir(path):
if os.path.isdir(filename):
os.chdir(filename)
j = os.path.abspath(os.getcwd())
mp3s = fnmatch.filter(os.listdir(j), '*.mp3')
if mp3s:
target = open("pls.m3u", 'w')
for filename in mp3s:
target.write(filename)
target.write("\n")
os.chdir(path)
All I would like to be able to do (if possible) is that when the script is looping through the folders that it ignores those which do NOT contain 'mp3s', and removes the 'pls.m3u'. I could only get the script to work properly if I created the 'pls.m3u' by default. The problem is that that creates a lot of empty 'pls.m3u' files in folders which contain only '.jpg' files for example. You get the idea.
I'm sure this script is blasphemous to Python users but any help would be greatly appreciated.
If I understand correctly, your core problem is that this script is creating a lot of empty pls.m3u files. That's because you're calling open before you've even checked whether you have anything you want to write.
A simple fix would be to change this:
target = open("pls.m3u", 'w')
j = os.path.abspath(os.getcwd())
for filename in os.listdir(j):
(title, extn) = os.path.splitext(filename)
if extn == ".mp3":
target.write(filename)
target.write("\n")
into this:
target = None
j = os.path.abspath(os.getcwd())
for filename in os.listdir(j):
(title, extn) = os.path.splitext(filename)
if extn == ".mp3":
if not target:
target = open("pls.m3u", 'w')
target.write(filename)
target.write("\n")
if target:
target.write("\n")
target.write("\n")
That is, only open the file the first time we decide we need to write to it.
A more Pythonic approach might be to do something like this:
j = os.path.abspath(os.getcwd())
mp3s = [filename for filename in os.listdir(j)
if os.path.splitext(filename)[1] == ".mp3"]
if mp3s:
target = open("pls.m3u", 'w')
for filename in mp3s:
target.write(filename)
target.write("\n")
target.write("\n")
target.write("\n")
That is, first create a list of the mp3s in memory (using a list comprehension here, though you could use a plain old for loop and append if you're more comfortable with that) and then open the file only if the resulting list is non-empty. (lists are truthy if non-empty)
I think you can do it in a two-level approach. First, copy the toplevel directory to another directory ignoring the directories which do not contain your mp3s files.
import shutil
IGNORE_PATTERNS = ('*mp3s')
shutil.copytree(SOURCE_DIR, TARGET_DIR, ignore=shutil.ignore_patterns(IGNORE_PATTERNS))
And then go ahead with the approach you are doing for files in your example code. Note that shutil.copytree has the ignore_patterns only from python2.5
Related
I have written a small script to hopefully iterate through my directory/folder and replace act with csv. Essentially, I have 11 years worth of files that have a .act extension and I just want to replace it with .csv
import os
files = os.listdir("S:\\folder\\folder1\\folder2\\folder3")
path = "S:\\folder\\folder1\\folder2\\folder3\\"
#print(files)
for x in files:
new_name = x.replace("act","csv")
os.rename(path+x,path+new_name)
print(new_name)
When I execute this, it worked for the first five files and then failed on the sixth with the following error:
FileNotFoundError: [WinError 2] The system cannot find the file specified: 'S:\\folder\\folder1\\folder2\\folder3\\file_2011_06.act' -> 'S:\\folder\\folder1\\folder2\\folder3\\file_2011_06.csv'
When I searched for "S:\folder\folder1\folder2\folder3\file_2011_06.act" in file explorer, the file opens. Are there any tips on what additional steps I can take to debug this issue?
Admittedly, this is my first programming script. I'm trying to do small/minor things to start learning. So, I likely missed something... Thank you!
In your solution, you use string's replace to replace "act" by "csv". This could lead to problems if your path contains "act" somewhere else, e.g., S:\\facts\\file_2011_01.act would become S:\\fcsvs\\file_2011_01.act and rename will throw a FileNotFoundError because rename cannot create folders.
When dealing with file names (e.g., concatenating path fragments, extracting file extensions, ...), I recommend using os.path or pathlib instead of direct string manipulation.
I would like to propose another solution using os.walk. In contrast to os.listdir, it recursively traverses all sub-directories in a single loop.
import os
def act_to_csv(directory):
for root, folders, files in os.walk(directory):
for file in files:
filename, extension = os.path.splitext(file)
if extension == '.act':
original_filepath = os.path.join(root, file)
new_filepath = os.path.join(root, filename + '.csv')
print(f"{original_filepath} --> {new_filepath}")
os.rename(original_filepath, new_filepath)
Also, I'd recommend to first backup your files before manipulating them with scripts. Would be annoying to loose data or see it becoming a mess because of a bug in a script.
import os
folder="S:\\folder\\folder1\\folder2\\folder3\\"
count=1
for file_name in os.listdir(folder):
source = folder + file_name
destination = folder + str(count) + ".csv"
os.rename(source, destination)
count += 1
print('All Files Renamed')
print('New Names are')
res = os.listdir(folder)
print(res)
I am trying to write a program in python that loops through data from various csv files within a folder. Right now I just want to see that the program can identify the files in a folder but I am unable to have my code print the file names in my folder. This is what I have so far, and I'm not sure what my problem is. Could it be the periods in the folder names in the file path?
import glob
path = "Users/Sarah/Documents/College/Lab/SEM EDS/1.28.20 CZTS hexane/*.csv"
for fname in glob.glob(path):
print fname
No error messages are popping up but nothing will print. Does anyone know what I'm doing wrong?
Are you on a Linux-base system ? If you're not, switch the / for \\.
Is the directory you're giving the full path, from the root folder ? You might need to
specify a FULL path (drive included).
If that still fails, silly but check there actually are files in there, as your code otherwise seems fine.
This code below worked for me, and listed csv files appropriately (see the C:\\ part, could be what you're missing).
import glob
path = "C:\\Users\\xhattam\\Downloads\\TEST_FOLDER\\*.csv"
for fname in glob.glob(path):
print(fname)
The following code gets a list of files in a folder and if they have csv in them it will print the file name.
import os
path = r"C:\temp"
filesfolders = os.listdir(path)
for file in filesfolders:
if ".csv" in file:
print (file)
Note the indentation in my code. You need to be careful not to mix tabs and spaces as theses are not the same to python.
Alternatively you could use os
import os
files_list = os.listdir(path)
out_list = []
for item in files_list:
if item[-4:] == ".csv":
out_list.append(item)
print(out_list)
Are you sure you are using the correct path?
Try moving the python script in the folder when the CSV files are, and then change it to this:
import glob
path = "./*.csv"
for fname in glob.glob(path):
print fname
I've searched through many answers on deleting multiple files based on certain parameters (e.g. all txt files). Unfortunately, I haven't seen anything where one has a longish list of files saved to a .txt (or .csv) file and wants to use that list to delete files from the working directory.
I have my current working directory set to where the .txt file is (text file with list of files for deletion, one on each row) as well as the ~4000 .xlsx files. Of the xlsx files, there are ~3000 I want to delete (listed in the .txt file).
This is what I have done so far:
import os
path = "c:\\Users\\SFMe\\Desktop\\DeleteFolder"
os.chdir(path)
list = open('DeleteFiles.txt')
for f in list:
os.remove(f)
This gives me the error:
OSError: [WinError 123] The filename, directory name, or volume label syntax is incorrect: 'Test1.xlsx\n'
I feel like I'm missing something simple. Any help would be greatly appreciated!
Thanks
Strip ending '\n' from each line read from the text file;
Make absolute path by joining path with the file name;
Do not overwrite Python types (i.e., in you case list);
Close the text file or use with open('DeleteFiles.txt') as flist.
EDIT: Actually, upon looking at your code, due to os.chdir(path), second point may not be necessary.
import os
path = "c:\\Users\\SFMe\\Desktop\\DeleteFolder"
os.chdir(path)
flist = open('DeleteFiles.txt')
for f in flist:
fname = f.rstrip() # or depending on situation: f.rstrip('\n')
# or, if you get rid of os.chdir(path) above,
# fname = os.path.join(path, f.rstrip())
if os.path.isfile(fname): # this makes the code more robust
os.remove(fname)
# also, don't forget to close the text file:
flist.close()
As Henry Yik pointed in the commentary, you need to pass the full path when using os.remove function. Also, open function just returns the file object. You need to read the lines from the file. And don't forget to close the file. A solution would be:
import os
path = "c:\\Users\\SFMe\\Desktop\\DeleteFolder"
os.chdir(path)
# added the argument "r" to indicates only reading
list_file = open('DeleteFiles.txt', "r")
# changing variable list to _list to do not shadow
# the built-in function and type list
_list = list_file.read().splitlines()
list_file.close()
for f in _list:
os.remove(os.path.join(path,f))
A further improvement would be use list comprehension instead of a loop and a with block, which "automagically" closes the file for us:
with open('DeleteFiles.txt', "r") as list_file:
_list = list_file.read().splitlines()
[os.remove(os.path.join(path,f)) for f in _list]
I have a directory that contains a thousand or so txt files. I've read and explored these files with glob (searching for specific strings within the file) and I've appended the filenames of the files of interest to a list in Python, like so:
list_of_chosen_files = ['file2.txt', 'file10.txt', 'file17.txt', ...]
I'll be using this list for other things as well, but now I'm trying to figure out how to use the OS module to cross-reference the filenames in the directory against the list above and, if the filename is in that list, to add "1-" to the beginning of the filename. I've saved "1-" in a variable for reuse as well. Here's what I have so far: -
var = "1-"
import os
for filename in os.listdir("."):
if filename == list_of_chosen_files[:]:
os.rename(filename, var+filename)
print filename
It's running without any errors in anaconda, but nothing's printing and none of the files are getting renamed. I feel like it should be such an easy fix, but I'm concerned about poking around directories with the OS module if I don't really know what I'm doing yet.
Any help would be greatly appreciated! Thanks!
Your issue is this line:
if filename == list_of_chosen_files[:]:
You're comparing a single string (filename) to an entire list (list_of_chosen_files[:] just gives you back the whole list). If you want to check if the filename is in the list, use this:
if filename in list_of_chosen_files:
This will check to see if list_of_chosen_files contains filename.
Error : if filename == list_of_chosen_files[:]:
os.listdir(".")is only giving you back the basename results. Not full path. They don't exist in your current working directory. You would need to join them back with the root:
root = 'full Path of your directory'
for item in os.listdir(root):
fullpath = os.path.join(root, item)
os.rename(fullpath, fullpath.replace('filename', 'var+filename'))
I have lots of programming experience but this is my first python script. I am trying to add the prefix "00" to all the files in a specific folder. First I read the names of all the files and save them in an array. Then I sort through the array and add the prefix "00" then use the os.rename function but somewhere along the way I've messed up something.
import sys, os
file_list = []
for file in os.listdir(sys.argv[1]):
file_list.append(file)
for i in file_list:
file_list[i] = prevName
newName = '00' + file_list[i]
os.rename(prevName, newName)
I have a .py file in the folder with all the files I want to rename. The .py file contains the script above. When i double click the .py file a cmd window flashes and disappears and none of the file names have been changed. Any help would be appreciated, sorry if this is a very obvious mistake, my python level is quite n00b at the moment.
In addition to the answer by #Padraic, also make following changes to your code.
import sys, os
file_list = []
for f in os.listdir(sys.argv[1]):
file_list.append(f)
for i in range(len(file_list)):
prevName = file_list[i]
if prevName != 'stackoverflow.py': # Mention .py file so that it doesnt get renamed
newName = '00' + file_list[i]
os.rename(prevName, newName)
Check your indentation. The second for loop is not indented correctly.
for i in file_list:
file_list[i] = prevName
You are not iterating correctly. for loops in Python are like foreach loops you may know from other programming languages. i in for i in file_list actually gives you the list's elements, so you should be doing
for i in range(len(file_list)):
file_list[i] = ......
although it is not very pythonic nor generally a good idea to modify the collection that you're currently iterating over.
Your code errors because you provide no args so sys.argv[1] would give an IndexError, you would need to call the script with the dir name from a cmd prompt not double click it:
python your_script directory <- argv[1]
Or change the code and specify the path, you also need to join the path to the filename.
path = "full_path"
for f in os.listdir(path):
curr,new = os.path.join(path,f), os.path.join(path,"00{}".format(f))
os.rename(curr,new)
os.listdir returns a list so just iterate over that, you don't need to create a list and append to it.
for i in file_list: would also make each i a filename not an index so that would cause another error but as above you don't need to do it anyway.