You don't need long pathnames if you chdir
into the directory and just use relative paths to rmdir
.
Or, if you have a POSIX shell installed, or port this to the DOS equivalent:
# untested code, didn't bother actually testing since the OP already solved the problem.
while [ -d Folder1 ]; do
mv Folder1/Folder1/Folder1/Folder1 tmp # repeat more times to work in larger batches
rm -r Folder1 # remove the first several levels remaining after moving the main tree out
# then repeat to end up with the remaining big tree under the original name
mv tmp/Folder1/Folder1/.../Folder1 Folder1
rm -r tmp
done
(Using a shell variable to track where you renamed it for the loop condition is the other alternative to unrolling the loop like I did there.)
This avoids the CPU overhead of KenD's solution, which forces the OS to traverse the tree from the top to the n
th level every time a new level is added, checking permissions etc. So it has sum(1, n) = n * (n-1) / 2 = O(n^2)
time complexity. Solutions that pare off a chunk from the start of the chain should be O(n)
, unless Windows needs to traverse a tree when renaming its parent directory. (Linux/Unix doesn't.) Solutions that chdir
all the way down to the bottom of the tree and use relative paths from there, removing directories as they chdir
back up, should also be O(n)
, assuming the OS doesn't need to check all your parent directories every system call, when you do things while CDed somewhere.
find Folder1 -depth -execdir rmdir {} +
will run rmdir while CDed to the deepest directory. Or actually, find's -delete
option works on directories, and implies -depth
. So find Folder1 -delete
should do the exact same thing, but faster. Yeah, GNU find on Linux descends by scanning a directory, CDing to subdirectories with relative paths, then rmdir
with a relative path, then chdir("..")
. It doesn't rescan directories while ascending, so it would consume O(n)
RAM.
That was really an approximation: strace
shows it ACTUALLY uses unlinkat(AT_FDCWD, "tmp", AT_REMOVEDIR)
, open("..", O_DIRECTORY|...)
, and fchdir(the fd from opening the directory)
, with a bunch of fstat
calls mixed in, too. But the effect is the same if the directory tree isn't getting modified while find is running.
edit: Just for kicks, I tried this on GNU/Linux (Ubuntu 14.10, on a 2.4GHz first-gen Core2Duo CPU, on an XFS filesystem on a WD 2.5TB Green Power drive (WD25EZRS)).
time mkdir -p $(perl -e 'print "annoyingfoldername/" x 2000, "\n"')
real 0m1.141s
user 0m0.005s
sys 0m0.052s
find annoyingfoldername/ | wc
2000 2000 38019001 # 2k lines / 2k words / 38M characters of text
ll -R annoyingfoldername
... eventually
ls: cannot access ./annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername/annoyingfoldername: File name too long
total 0
?????????? ? ? ? ? ? annoyingfoldername
time find annoyingfoldername -delete
real 0m0.054s
user 0m0.004s
sys 0m0.049s
# about the same for normal rm -r,
# which also didn't fail due to long path names
(mkdir -p creates a directory and any missing path components).
Yes, really 0.05 seconds for 2k rmdir ops. xfs is quite good at batching metadata operations together in the journal, since they fixed meta data ops being slow like 10 years ago.
On ext4, create took 0m0.279s, delete with find still took 0m0.074s.