Mac Big Sur home folder permissions: Read-only file system when renaming files
UPDATE #2
I was able to successfully rename the files using sed:
for f in *.Rdat; do mv $f $(echo $f | sed "s/PCC-//"); done
UPDATE I discovered I can rename individual files:
mv 'PCC-ASR-L.Rdat' 'ASR-L.Rdat'
So evidently the problem occurs only when trying to batch rename in a for loop
. I would still like to understand why.
ORIGINAL POST
After upgrading to Big Sur
from Catalina
, I tried to use the terminal to rename some files in a subfolder of my Home
folder. I had created and used the subfolder before upgrading. Specifically, I tried renaming a group of Rdat
files using a bash for loop
. I could do this under Catalina, but now I get an error. Here, I am trying to replace 'PCC-' in each file name with an empty string (i.e. ''
):
for f in *.Rdat; do mv $f ${f/PCC-//}; done
This yields an error for every file, like this (for file PCC-ASR-H.Rdat
):
mv: /ASR-H.Rdat: Read-only file system
This seems strange because as owner of the folder I have write permissions
:
drwxr-xr-x 8 mike staff 256 Nov 21 15:04 Rdatafiles
And I have write permissions
for the files in the folder (example):
-rw-rw-r--@ 1 mike staff 10926 Dec 4 18:26 PCC-ASR-H.Rdat
I tried disabling SIP
in Recovery Mode
:
csrutil disable
But the problem remains. Is it possible to make subfolders of the home folder writeable under Big Sur
? Are there some additional changes I need to make to the system (i.e. permissions
) to enable write access? Or do I now need to move my work files out of Home
and into, say, Home/Documents
, to avoid this issue?
The problem is the double forward-slash in ${f/PCC-//}
. Unlike a sed substitution pattern, there's no /
at the end of the replacement pattern (it's terminated by }
), so the extra /
is taken as the replacement string. This turns e.g. "PCC-ASR-L.Rdat" into "/ASR-L.Rdat", which (because of the "/") is at the root of the filesystem... which is read-only.
When I'm doing things like batch renames, I also often don't get everything right on the first try, so I tend to do a dry run with echo
in front of the mv
(or cp
or rm
or...) command first, so I can see what's going to happen before actually running it. I also strongly recommend using mv -i
or mv -f
, so if there's any sort of naming conflict it won't just silently and irreversibly overwrite files. Also, putting double-quotes around variable references is a good idea, in case any filenames contain weird characters.
So my dry run would look something like this:
for f in *.Rdat; do echo mv -i "$f" "${f/PCC-/}"; done
...and if that looked right, I'd hit up-arrow to get it back, delete the "echo", and re-run it for real.
If you need to troubleshoot in even more detail, using set -x before the command will show what the shell thinks is going on (i.e. what the command looks like after substitutions are performed) in cases like this.