Relatively new to python, trying to move files based on type from one directory to another.
import shutil
import os
source = 'C:\Users\home\Desktop'
Unsorted = 'C:\Users\home\Desktop\'
Sorted = 'B:\Pictures'
file = os.listdir(source)
for f in file("Unsorted"):
if file.endswith(".png",".jpg"):
print(os.path.join("Sorted", file))
I would appreciate any help. Thank you.
Edit
Thank you for the help and the links. I really appreciate it. I am reading automatetheboringstuff, and Modern Python Cookbook (2018).
import os
source = 'C:\\Users\\home\\Desktop'
sorted = 'B:\\Pictures'
for f in os.listdir(source):
if f.endswith((".png",".jpg",".jpeg")):
print(os.path.join(sorted, f))
I believe it works, since I am not getting any errors, but it's not moving the files. It seems to work here: link. Maybe it doesn't work between drives? Anyway, thank you!
EDIT I got it to work!
import os
import shutil
source = os.path.join('C:\\Users\\home\\Desktop')
sort = os.path.join('B:\\Pictures')
for f in os.listdir(source):
if f.endswith((".png",".jpg",".jpeg")):
shutil.move(os.path.join(source, f), sort)
Thank you everyone for your help! I hope you guys have a great rest of your day! Thanks. :D
See the comments inline.
#import shutil # commented out as this is not used for anything here
import os
# use r'...' strings for file names with backslashes (or use forward slashes instead)
source = r'C:\Users\home\Desktop'
#Unsorted = r'C:\Users\home\Desktop\' # also not used
Sorted = r'B:\Pictures'
# listdir produces an unsorted list of files so no need to muck with it
for f in os.listdir(source):
# you had the wrong variable name here, and missing parens around the tuple
if f.endswith((".png",".jpg")):
# again, the variable is f
# and of course "Sorted" is just a string, you want the variable
print(os.path.join(Sorted, f))
Some general advice:
Python has good documentation and is easy to play around with; just starting up Python and typing in a fragment of your program lets you try things until you can see what to write in your program to make it do what you want, without guesswork, typos, or unfounded expectations.
Don't use reserved keywords for your variables. Understand the difference between a string and a variable name (and a keyword).
Many of the things you had wrong are extremely common beginner errors. A bit of googling (especially with an error message or a phrase describing what's not working) will very often lead you to an excellent answer on Stack Overflow explaining exactly what's wrong and how to fix it.
Thus, don't cram too much into a single question. Most of the time, if your question is specific enough, you don't even have to ask it once you see what's wrong.
To concretize with an example, in the Python interactive REPL, maybe you are actually wondering whether endswith works with an uppercase file name, so you try it:
>>> 'PANGEA.PNG'.endswith(".png",".jpg")
This gives you a somewhat incredulous message that "slice indices must be integers" which isn't very helpful by itself (until you understand what it's trying to say -- endswith wants a "suffix" argument and an (optional) "start" argument, which is then used to "slice" the string; and ".jpg" isn't a valid value for start, so slicing fails because of that) but very easy to search for -- this Stack Overflow question is literally my first google hit for the search endswith "slice indices must be integers" and so you figure out what was wrong with your attempt, and what the error message is telling you, and now you go ahead and fix one of the small bugs in your code so far, and proceed with the next experiment (maybe check that os.path.join("Sorted", "PANGEA.PNG") looks like what you expect?)
Related
I have a folder, which I'm trying to input in Python as a string, for example folder = r'C:\Users\Desktop' or folder = 'C:\\Users\\Desktop'
I'm then using pyautogui.typewrite(folder), but when I do so the directory name is pasted as C'<Users<Desktop
Do you know what is causing that and how can I solve this issue?
Thank you!
[Solution]
Combining both inputs from "SuperStormer" (thanks a lot!!) along with some additional research and adaptation I manage to solve the issue by:
Change the keyboard to English - looks like pyautogui emulates the typing of the keyboard, and it doesn't support any language other than english - this almost solved my issue, it solved the backslashes, but then the ":" started to become a "?", like 'C?\Users\Desktop'
Use pyperclip to paste string directly from keyboard - I did some simulations and that would have worked, except that I already had something on my clipboard that had to be used in a later step, and as I couldn't find a way to reference more than two clipboards at a time that didn't work right away, but after some workarounds based on that function I finally got to the solution
I'm looking for a simple method of identifying the last position of a string inside another string ... for instance. If I had: file = C:\Users\User\Desktop\go.py
and I wanted to crop this so that file = go.py
Normally I would have to run C:\Users\User\Desktop\go.py through a loop + find statement, and Evey time it encountered a \ it would ask ... is the the last \ in the string? ... Once I found the last \ I would then file = file[last\:len(file)]
I'm curious to know if there is a faster neater way to do this.. preferably without a loop.
Something like file = [file('\',last):len(file)]
If there is nothing like what I've shown above ... then can we place the loop inside the [:] somehow. Something like file = [for i in ...:len(file)]
thanks :)
If it is only about file paths, you can use os.path.basename:
>>> import os
>>> os.path.basename(file)
'go.py'
Or if you are not running the code on Windows, you have to use ntpath instead of os.path.
You could split the string into a list then get the last index of the list.
Sample:
>>> file = 'C:\Users\User\Desktop\go.py'
>>> print(file.split('\\')[-1])
go.py
I agree with Felix on that file paths should be handled using os.path.basename. However, you might want to have a look at the built in string function rpartition.
>>> file = 'C:\Users\User\Desktop\go.py'
>>> before, separator, after = file.rpartition('\\')
>>> before
'C:\\Users\\User\\Desktop'
>>> separator
'\\'
>>> after
'go.py'
There's also the rfind function which gives you the last index of a substring.
>>> file.rfind('\\')
21
I realize that I'm a bit late to the party, but since this is one of the top results when searching for e.g. "find last in str python" on Google, I think it might help someone to add this information.
For the general purpose case (as the OP said they like the generalisation of the split solution)...... try the rfind(str) function.
"myproject-version2.4.5.customext.zip".rfind(".")
edit: apologies, I hadn't realized how old this thread was... :-/
For pathname manipulations you want to be using os.path.
For this specific problem you want to use the os.path.basename(path) function which will return the last component of a path, or an empty string if the path ends in a slash (ie. the path of a folder rather than a file).
import os.path
print os.path.basename("C:\Users\User\Desktop\go.py")
Gives:
go.py
System: Python 2.6 on Windows 7 64 bit
Recently I did a lot of path formatting in Python. Since the string modifications are always dangerous I started to do it the proper way by using the 'os.path' module.
The first question is if this is the right way to to handle incoming paths? Or can I somehow optimize this?
sCleanPath = sRawPath.replace('\n', '')
sCleanPath = sCleanPath.replace('\\', '/')
sCleanPythonPath = os.path.normpath(sCleanPath)
For formatting the 'sCleanPythonPath' now I use only functions from the 'os.path' module. This works very nice and I didn't had any problems so far.
There is only one exception. I have to change paths so they point not longer on a network storage but on a local drive. Is started to use 'os.path.splitunc()' in conjunction with 'os.path.join()'.
aUncSplit = os.path.splitunc(sCleanPythonUncPath)
sLocalDrive = os.path.normpath('X:/mount')
sCleanPythonLocalPath = (os.path.join(sLocalDrive, aUncSplit[1]))
Unfortunately this doesn't work due to the nature of how absolute paths are handled using 'os.path.join()'. All the solutions I found in the web are using string replacements again which I want to avoid by using the 'os.path' module. Have I overseen anything? Is there another, maybe a better way to do this?
All comments on this are very welcome!
You could optimize the first part slightly by removing the replace() call because on Windows normpath() converts forward slashes to backward slashes:
sCleanPath = sRawPath.replace('\n', '')
sCleanPythonPath = os.path.normpath(sCleanPath)
Here's something that would make the second part of your question work without doing a string replacement:
sSharedFolder = os.path.relpath(os.path.splitunc(sCleanPythonUncPath)[1], os.sep)
sLocalDrive = os.path.normpath('X:/mount') # why not hardcode the result?
sCleanPythonLocalPath = os.path.join(sLocalDrive, sSharedFolder)
Question
It seems that PyWin32 is comfortable with giving null-terminated unicode strings as return values. I would like to deal with these strings the 'right' way.
Let's say I'm getting a string like: u'C:\\Users\\Guest\\MyFile.asy\x00\x00sy'. This appears to be a C-style null-terminated string hanging out in a Python unicode object. I want to trim this bad boy down to a regular ol' string of characters that I could, for example, display in a window title bar.
Is trimming the string off at the first null byte the right way to deal with it?
I didn't expect to get a return value like this, so I wonder if I'm missing something important about how Python, Win32, and unicode play together... or if this is just a PyWin32 bug.
Background
I'm using the Win32 file chooser function GetOpenFileNameW from the PyWin32 package. According to the documentation, this function returns a tuple containing the full filename path as a Python unicode object.
When I open the dialog with an existing path and filename set, I get a strange return value.
For example I had the default set to: C:\\Users\\Guest\\MyFileIsReallyReallyReallyAwesome.asy
In the dialog I changed the name to MyFile.asy and clicked save.
The full path part of the return value was: u'C:\Users\Guest\MyFile.asy\x00wesome.asy'`
I expected it to be: u'C:\\Users\\Guest\\MyFile.asy'
The function is returning a recycled buffer without trimming off the terminating bytes. Needless to say, the rest of my code wasn't set up for handling a C-style null-terminated string.
Demo Code
The following code demonstrates null-terminated string in return value from GetSaveFileNameW.
Directions: In the dialog change the filename to 'MyFile.asy' then click Save. Observe what is printed to the console. The output I get is u'C:\\Users\\Guest\\MyFile.asy\x00wesome.asy'.
import win32gui, win32con
if __name__ == "__main__":
initial_dir = 'C:\\Users\\Guest'
initial_file = 'MyFileIsReallyReallyReallyAwesome.asy'
filter_string = 'All Files\0*.*\0'
(filename, customfilter, flags) = \
win32gui.GetSaveFileNameW(InitialDir=initial_dir,
Flags=win32con.OFN_EXPLORER, File=initial_file,
DefExt='txt', Title="Save As", Filter=filter_string,
FilterIndex=0)
print repr(filename)
Note: If you don't shorten the filename enough (for example, if you try MyFileIsReally.asy) the string will be complete without a null byte.
Environment
Windows 7 Professional 64-bit (no service pack), Python 2.7.1, PyWin32 Build 216
UPDATE: PyWin32 Tracker Artifact
Based on the comments and answers I have received so far, this is likely a pywin32 bug so I filed a tracker artifact.
UPDATE 2: Fixed!
Mark Hammond reported in the tracker artifact that this is indeed a bug. A fix was checked in to rev f3fdaae5e93d, so hopefully that will make the next release.
I think Aleksi Torhamo's answer below is the best solution for versions of PyWin32 before the fix.
I'd say it's a bug. The right way to deal with it would probably be fixing pywin32, but in case you aren't feeling adventurous enough, just trim it.
You can get everything before the first '\x00' with filename.split('\x00', 1)[0].
This doesn't happen on the version of PyWin32/Windows/Python I tested; I don't get any nulls in the returned string even if it's very short. You might investigate if a newer version of one of the above fixes the bug.
ISTR that I had this issue some years ago, then I discovered that such Win32 filename-dialog-related functions return a sequence of 'filename1\0filename2\0...filenameN\0\0', while including possible garbage characters depending on the buffer that Windows allocated.
Now, you might prefer a list instead of the raw return value, but that would be a RFE, not a bug.
PS When I had this issue, I quite understood why one would expect GetOpenFileName to possibly return a list of filenames, while I couldn't imagine why GetSaveFileName would. Perhaps this is considered as API uniformity. Who am I to know, anyway?
Am I correct in thinking that that Python doesn't have a direct equivalent for Perl's __END__?
print "Perl...\n";
__END__
End of code. I can put anything I want here.
One thought that occurred to me was to use a triple-quoted string. Is there a better way to achieve this in Python?
print "Python..."
"""
End of code. I can put anything I want here.
"""
The __END__ block in perl dates from a time when programmers had to work with data from the outside world and liked to keep examples of it in the program itself.
Hard to imagine I know.
It was useful for example if you had a moving target like a hardware log file with mutating messages due to firmware updates where you wanted to compare old and new versions of the line or keep notes not strictly related to the programs operations ("Code seems slow on day x of month every month") or as mentioned above a reference set of data to run the program against. Telcos are an example of an industry where this was a frequent requirement.
Lastly Python's cult like restrictiveness seems to have a real and tiresome effect on the mindset of its advocates, if your only response to a question is "Why would you want to that when you could do X?" when X is not as useful please keep quiet++.
The triple-quote form you suggested will still create a python string, whereas Perl's parser simply ignores anything after __END__. You can't write:
"""
I can put anything in here...
Anything!
"""
import os
os.system("rm -rf /")
Comments are more suitable in my opinion.
#__END__
#Whatever I write here will be ignored
#Woohoo !
What you're asking for does not exist.
Proof: http://www.mail-archive.com/python-list#python.org/msg156396.html
A simple solution is to escape any " as \" and do a normal multi line string -- see official docs: http://docs.python.org/tutorial/introduction.html#strings
( Also, atexit doesn't work: http://www.mail-archive.com/python-list#python.org/msg156364.html )
Hm, what about sys.exit(0) ? (assuming you do import sys above it, of course)
As to why it would useful, sometimes I sit down to do a substantial rewrite of something and want to mark my "good up to this point" place.
By using sys.exit(0) in a temporary manner, I know nothing below that point will get executed, therefore if there's a problem (e.g., server error) I know it had to be above that point.
I like it slightly better than commenting out the rest of the file, just because there are more chances to make a mistake and uncomment something (stray key press at beginning of line), and also because it seems better to insert 1 line (which will later be removed), than to modify X-many lines which will then have to be un-modified later.
But yeah, this is splitting hairs; commenting works great too... assuming your editor supports easily commenting out a region, of course; if not, sys.exit(0) all the way!
I use __END__ all the time for multiples of the reasons given. I've been doing it for so long now that I put it (usually preceded by an exit('0');), along with BEGIN {} / END{} routines, in by force-of-habit. It is a shame that Python doesn't have an equivalent, but I just comment-out the lines at the bottom: extraneous, but that's about what you get with one way to rule them all languages.
Python does not have a direct equivalent to this.
Why do you want it? It doesn't sound like a really great thing to have when there are more consistent ways like putting the text at the end as comments (that's how we include arbitrary text in Python source files. Triple quoted strings are for making multi-line strings, not for non-code-related text.)
Your editor should be able to make using many lines of comments easy for you.