#πŸ”’ Can't rename a folder that can be listdir'd because "cannot find file specified"

134 messages Β· Page 1 of 1 (latest)

rich egret
#

Running Windows 10, trying to rename a bunch of folders to remove ellipsis from them, and I'm trying to os.rename( path + oldname, path + newname ) but I get [WinError 2] The system cannot find the file specified despite the fact that os.listdir( path + oldname ) works perfectly fine, and the oldname directory shows up in os.listdir( path )

hollow frigateBOT
#

@rich egret

Python help channel opened

Remember to:

  • Ask your Python question, not if you can ask or if there's an expert who can help.
  • Show a code sample as text (rather than a screenshot) and the error message, if you've got one.
  • Explain what you expect to happen and what actually happens.

:warning: Do not pip install anything that isn't related to your question, especially if asked to over DMs.

undone forge
#

!pathlib

hollow frigateBOT
#
The `pathlib` module

Python 3 comes with a new module named Pathlib. Since Python 3.6, pathlib.Path objects work nearly everywhere that os.path can be used, meaning you can integrate your new code directly into legacy code without having to rewrite anything. Pathlib makes working with paths way simpler than os.path does.

Feature spotlight:

  • Normalizes file paths for all platforms automatically
  • Has glob-like utilites (eg. Path.glob, Path.rglob) for searching files
  • Can read and write files, and close them automatically
  • Convenient syntax, utilising the / operator (e.g. Path('~') / 'Documents')
  • Can easily pick out components of a path (eg. name, parent, stem, suffix, anchor)
  • Supports method chaining
  • Move and delete files
  • And much more

More Info:

undone forge
rich egret
#

I'll give it a shot

#

this is mostly for a single script since I have like 30% of some 40,000 directories with "..." at the end and I'm just trying to get rid of those

#

and not really for a project of any sort

undone forge
#

aha, okay, but probably good to learn the more modern way of doing it for future scripts anyways πŸ˜‰

rich egret
#

true true

undone forge
#

mostly you can ignore the different windows and unix specific classes from pathlib and just juse Path all the time

rich egret
#

so if I'm understanding this correctly

from pathlib import Path
source_dir = Path( path + oldname )
target_dir = Path( path + newname )
source_dir.rename( target_dir )

right?

undone forge
#

you just use / between strings, string variables or Path objects to concatenate it together and the library will sort out what actually goes in between different components in the path

rich egret
#

hmm still running into the same error, can't find file specified

undone forge
#

also, where do you get the path and oldname and newname variables from?

rich egret
#

just elsewhere in a for loop, didn't think it was necessary to post the full code

#

but I can if you want

undone forge
#

just so that it's easier to help out

#

because it might be a better way to go about the whole thing

rich egret
#

so haven't yet added the pathlib part, but this is what I'm doing ```py
import os

search_for = '...'

for oldname in os.listdir( path ):
if os.path.isfile( path + oldname ):
continue
if search_for not in oldname:
continue

newname = oldname.replace( search_for, '' )
try:
    os.rename( path + oldname, path + newname )
except WindowsError as err:
    print(err)
    break
undone forge
#

and you only want to look at that dir level, not subdirectories, or would you want to include them as well?

rich egret
#

correct

#

I'm just looking at this directory level

#

not subdirectories

#

in path I'm expecting only files and directories with only files, so there shouldn't be any sub directories

#

so is this what I should be doing?

import os
from pathlib in Path

search_for = '...'

for oldname in os.listdir( path ):
    if os.path.isfile( path + oldname ):
        continue
    if search_for not in oldname:
        continue
    oldpath = Path( path + oldname )
    newname = oldname.replace( search_for, '' )
    newpath = Path( oldname.replace( search_for, '' )
    try:
        oldpath.replace( new_path )
    except WindowsError as err:
        print(err)
        break
undone forge
#

okay, test this out

from pathlib import Path

for dir in Path().cwd().glob("*.../"):
    dir.rename(str(dir).removesuffix("..."))
#

that is for doing the search in the current directory, hence cwd() in there

rich egret
#

ah gotcha

#

tbh I usually don't actually run python in the working directory hence why I usually just use a path variable

undone forge
#

you can put a path in there instead

rich egret
#

fair enough

#

but it is good to know about cwd()

undone forge
#
from pathlib import Path

for dir in Path("/my/path/here").glob("*.../"):
    dir.rename(str(dir).removesuffix("..."))
#

or just:

from pathlib import Path

for dir in Path(path).glob("*.../"):
    dir.rename(str(dir).removesuffix("..."))
rich egret
#

huh so glob is like grabbing something almost regex style?

undone forge
#

if you define path elsewhere

#

yeah, but it got its own pattern matching

rich egret
#

gotcha, neat

undone forge
#

i put a / at the end of the glob pattern to tell it to only look for directories

rich egret
#

AttributeError: 'str' object has no attribute 'removesuffix'

rich egret
undone forge
#

if i wanted it to go for the directory and all subdirectories i would have used **/*.../ as the glob pattern instead

undone forge
rich egret
#

3.8

undone forge
#

😞

rich egret
#

oof

undone forge
#

well then, we can do it without it, it's just a convenience function anyways

rich egret
#

yeah, 3.8.3 apparently

#

makes sense

#

how's this? str(dir).rstrip("...")

undone forge
#

i think that is equal to str(dir).rstrip(".") and will remove any number of . at the end of the string

rich egret
#

hm fair

#

either way still get the same error

undone forge
#

but might be okay in this case

rich egret
#

FileNotFoundError: [WinError 2] The system cannot find the file specified

undone forge
#

is it a directory or is it a symlink

rich egret
#

directory

#

part of the reason I'm trying to remove the ellipsis is because I've been noticing weird behavior in all of the directories in path that have ellipsis

#

so I figured trying to remove the ellipsis may make the directories behave like normal, but I'm not sure

#

I was trying to move them to my NAS over SMB and something about that file transfer has left these directories in a weird state

#

Windows can't find any files in the directories but I can os.listdir them in Python and get their contents perfectly fine

#

Windows also can't open the directories in File Explorer

undone forge
#

that sounds really strange

rich egret
#

lol yeah

undone forge
#

so the directories that you are trying to rename resides on a NAS that you are accessing over SMB with python?

rich egret
#

they're local, I'm trying to move them to a NAS

undone forge
#

oh, okay, that makes sense

rich egret
#

now that I check tho, there are some that are duplicated on the NAS already

#

same directory name but without the ellipsis

undone forge
#

i do think windows can take issue with files and directories ending in ..., i think i have seen that before

rich egret
#

tbh I don't think they were supposed to be ending with ..., I think for some reason something about this file transfer made them end with it

undone forge
#

have you transferred them from the NAS to your local drive over SMB and then they ended up with those file names?

rich egret
#

nah other way, I'm trying to go from local to NAS

#

oh right I forgot to mention

#

I had a file transfer going then File Explorer crashed in the middle of it

#

that's probably what's causing this weirdness

#

but still need to find some way to fix it

#

I think the ones that end with ... are the files that were marked for deletion after a successful file transfer

undone forge
#

but the directories with the three dots at the end is on your local drive, right?

rich egret
#

yep

undone forge
#

i don't remember when, but it was quite a long time ago, i too had a problem with a few directories with three dots at the end on i windows system

rich egret
#

so in order of events: local files don't have ..., I try to transfer them to NAS, in the middle of the transfer File Explorer crashes, I check local files again, now there's a bunch of directories with ... at the end which I can't open in windows

undone forge
#

luckily for me i had cygwin installed on the system so that i could just open a bash prompt and fix it manually (because there wasn't a lot of them in my case)

#

msys2 would probably work just as well as cygwin, i think i even had both installed on that system

rich egret
#

looking up some more info about it, apparently Win32 doesn't let you end directories with . and all that would end a directory name just get removed under normal circumstances

#

apparently you can still remove them in CLI with rmdir tho

undone forge
#

yeah, you are right, i just accessed a remote windows 10 system and tried it out on just now

#

the number also correspond to how many dots there are at the end of each directory name

rich egret
#

even CLI can't delete them >_>

#

The system cannot find the file specified.

undone forge
#

can't access any of them besides the directory named testing

rich egret
#

oh found out how to delete them

undone forge
#

yeah, your right, CMD can't access or delete it either

rich egret
#

because it contains a . the CMD thinks it's a file, so you have to append a \ so it knows it's a directory

undone forge
#

but are you okay just deleting the directories?

rich egret
#

most of them are already backed up and it's not critical data so I'm not going to fret about losing whatever like 5 might have been in progress during the transfer crash

#

huh it seems to work in python as well

#

just adding \ to the end

#

might just try making a new directory with what it was supposed to be named, move the contained files to the new directory, then delete the old problematic directories

undone forge
#

wow, using 7-Zip i can brows the directory just fine πŸ˜„

#

and also rename it

#

@rich egret still there?

rich egret
#

yep just finished running the script

#

the original scripts worked once I appended "\\" to the end of the directory names so it stopped looking for a file named "blah blah..." and instead found the directories named "blah blah..."

#

just had to add a little bit so it handles some of the duplicates but it works now

#

I appreciate your help, glad I could finally un mess up these files x_x

undone forge
#

but if you wanted to explore those directories you could at least do that with 7-Zip

rich egret
#

true

undone forge
#

and it was also easy to rename the directories using 7-Zip manually if it wasn't a lot of them, so that they become usable from windows explorer again

rich egret
#

yeah, unfortunately that would not have been feasible for my issue, since it was a few thousand problem directories

undone forge
#

good that you could script your way around it then πŸ‘

rich egret
#

lol yeah that's the reason I was trying python to fix it xD

undone forge
#

just noticed something else in my test directory
the directory named test1. with only one dot at the end messes everything up for python on windows

#

but if i rename it test1.. (just add another dot to it) it's all fine and is accessible with python on windows again

#

so watch out for the directories with a single dot at the end of the name, they seem to be the most problematic

#

not even adding "\\" to the end of the directory name helps python to be able to operate on the directory with just a single dot at the end of the name
so i don't know how i would fix that without doing it manually with 7-Zip or scripting it with bash in bash script with cygwin installed

#

this is the code i ran as the .rename() method of Path from pathlib couldn't rename any of the directories ending with any amounts of dots at the end, but os.rename could, at least if there was two or more dots at the end, but not directories with a single dot at the end

import os
from pathlib import Path

for dir in Path().cwd().glob("*./"):
    os.rename(str(dir) + "\\", str(dir).rstrip("."))
#

don't know why 🀷

rich egret
#

agreed, -shrug-

#

that being said, after running the script, I have no directories with '.' in them

undone forge
#

good, so problem solved then?

rich egret
#

yep

#

actually had to run the script another time because file explorer crashed again, but I'm now using a different program for transferring the files over to the NAS that can better handle errors

#

!close

hollow frigateBOT
#
Python help channel closed

This help channel has been closed and it's no longer possible to send messages here. If your question wasn't answered, feel free to create a new post in #1035199133436354600. To maximize your chances of getting a response, check out this guide on asking good questions.