8

I am trying to do as the title explains, but am given the message WinError2: cannot find the file specified 'New Text Document.txt' -> 'new_text_document.txt' with the code snippet below. Yes, my Desktop is on drive letter D, and this assumes the target directory is named 'directory'. I have a sample file in the directory named 'New Text Document.txt'. I just can't figure out where the problem is.

import os
path = 'D:\Desktop\directory'
filenames = os.listdir(path)
for filename in filenames:
    os.rename(filename, filename.replace(' ', '_').lower())
Gl0rph
  • 83
  • 1
  • 1
  • 3

4 Answers4

8

A one-liner using list comprehension:

import os

directory = 'D:\Desktop\directory'

[os.rename(os.path.join(directory, f), os.path.join(directory, f).replace(' ', '_').lower()) for f in os.listdir(directory)]

list-comprehension borrowed from answer Batch Renaming of Files in a Directory

Community
  • 1
  • 1
  • Brilliant, though i must admit that's a little hard to follow for a novice like me. Could you explain what f is doing? – Gl0rph May 02 '17 at 01:21
  • Sure! Sorry about the confusion, `f` is just a variable name for each file in the directory that is getting renamed. So in plain speak it would be for each `f in os.listdir(directory)` ("for each file in the directory"). Of course, feel free to use change/ use other variable names, being consistent with renaming all of them, and use variable names that are easy to understand. – chickity china chinese chicken May 02 '17 at 01:23
  • This code is *almost identical* to the code in lsalamon's answer, which his answer probably is easier to read (for each...do this), and `f` in my example would be the same variable as `filename` in lsalamon's answer. – chickity china chinese chicken May 02 '17 at 01:26
  • Ahh, ok. Things are starting to make sense. I wound up using something very similar to you and isalamon's answers, just formatted in a way to help me read it. Thank you for the explanation! – Gl0rph May 02 '17 at 01:38
  • Great, glad to hear you got something working that makes sense for you, good luck. Cheers! – chickity china chinese chicken May 02 '17 at 01:41
  • It should be `os.path.join(directory, f.replace(' ', '_').lower()))` if you want to replace only the base file name and not the folder names too. – Leponzo Nov 14 '20 at 17:23
5

use the full file naming for safer os operations:

import os
path = 'D:\\test'
for filename in os.listdir(path):
    #print(filename)
    os.rename(os.path.join(path,filename),os.path.join(path, filename.replace(' ', '_').lower())) 
lsalamon
  • 788
  • 7
  • 12
  • 1
    How is using string concatenation *safer os operation*? It would be better to use `os.path.join` or move on to use `pathlib.Path` altogether – Tomerikoo Jun 18 '20 at 19:43
1

Alternative method using os.walk(directory) if you want to do this recursively through several levels of folders:

import os

directory = r'D:\Desktop\directory'

# Use underscore? Otherwise defaults to hyphen
is_use_underscore = True
char_to_use = '_' if is_use_underscore else '-'   

print("Renaming files now!")
for root, dirs, files in os.walk(directory):
    print(f"root: {root}")
    print(f"dirs: {dirs}")
    print(f"files: {files}")

    for current_filename in files:
        new_filename = current_filename.replace(' ', char_to_use)

        print(f"current filename: {current_filename}")
        print(f"    new filename: {new_filename}")

        os.rename(
            os.path.join(root, current_filename), 
            os.path.join(root, new_filename)
        )   

print("All done!")
Sean McCarthy
  • 4,838
  • 8
  • 39
  • 61
0

Because you did not specify the directory where the New Text Document.txt is for the os.rename function. You can just add this line before the for loop.

os.chdir(path)

And either use raw strings or full file paths, because the way you defined path will also give you an error.

path = r'D:\Desktop\directory' or path = 'D:\\Desktop\\directory'

A.Sherif
  • 144
  • 2
  • 8
  • I'm not sure what you mean.. Is D:\Desktop\directory not a full file path? – Gl0rph May 02 '17 at 01:19
  • @Gl0rph If you use path='"C:\Desktop\directory"' the \ will act as an escape character. So it wont give you the expected result. That's why you should use two backslashes '\\' to cancel that escape character. or use any other way as mentioned, check this [answer](http://stackoverflow.com/a/2953843/2998262) – A.Sherif May 02 '17 at 01:25
  • Ohhh wow, that's a huge help! Thank you Sherif, that explains why a few other scripts I've been playing around with aren't working right... – Gl0rph May 02 '17 at 01:33
  • @Gl0rph No problem! Am glad to help. – A.Sherif May 02 '17 at 01:35