Search code examples
bashmacosterminalzshapfs

What is the fastest way to rename a folder?


Update

Based on the answer about rename;

python3 \
  -c "from os import rename; from sys import argv; rename(argv[1], argv[2])" \
  $original $temp

seems the fastest for this computer's situation.

it shouldn't be. But here we are.


I'm on macOS Sequoia, 15.2 -- on an encrypted drive using APFS. in VM testing, encryption doesn't have a measurable effect on these times, but it appears moreso that the design of APFS, via the Global Lock: https://gregoryszorc.com/blog/2018/10/29/global-kernel-locks-in-apfs/ is what is slowing things down.

There is also this bug report to openradar: https://openradar.me/45648013

So, we must use tricks to delete things to try to become as fast as ext4 or other reasonable file systems.

This is my situation:

Using mv:

❯ time ( mv node_modules nm )

real    0m7.578s
user    0m0.001s
sys 0m0.003s

move via rm

aka move out of existence.

my ultimate goal anyway is deleting

❯ time ( rm -rf node_modules )

real    0m17.763s
user    0m0.132s
sys 0m11.539s

move via rsync

❯ time ( rsync -av --delete $(mktemp -d)/ ./node_modules )
Transfer starting: 1 files

sent 79 bytes  received 26 bytes  70 bytes/sec
total size is 0  speedup is 0.00

real    0m16.208s
user    0m0.376s
sys 0m11.505s

I'm surprised mv isn't instant -- because it should just be an inode update, yeah?

In addition to the openradar issue, it does seem like others have noticed this problem:

But maybe, mac folks don't typically work in large projects? maybe they just put up with it because "mac is good"? don't know how fast things can be? idk. it's been weird.


@fravadona suggested I disable my AV.

I have actually. things used to be way worse -- 2-4x worse. The AV used was MalwareBytes, and ... well, malware is right in the name... so... if you have a choice of AV... probably don't want that one.

There is still more Software on here for me to test:

  • CyberHaven
  • Kandji ESF

While I can't disable these things (I don't own the hardware I'm testing on), I can boot up a macOS VM and run the same test:

Here are the results:

mv

time ( mv node_modules nm.bak )

real  0m0.011s

rm -rf

time ( rm -rf node_modules )

real    0m12.812s

so... that's kind nuts.


Solution

  • mv has to deal with moves across physical partitions which you don't need.

    From man mv:

    As the rename(2) call does not work across file systems, mv uses cp(1) and rm(1) to accomplish the move.

    Take a look at man 2 rename which is exposed by, eg, python's os.rename.

    The operation may fail if src and dst are on different filesystems. Use shutil.move() to support moves to a different filesystem.