1

I want to delete a directory with its contents recursively, and then re-create it with the same name and permissions. That directory may or may not be created or owned by me earlier before delete, but I am sure I wouldn't touch any folder created by Root, just the folders created/owned by Users same level as me.

I have the command to recursively delete the directory with all its contents:

rm -rf path/to/somefolder 2> /dev/null
## OR ##
rm -rf /some/path/.* 2> /dev/null && rm -rf /some/path 2> /dev/null

But how can I get the permissions before deletions and then reapply them to the newly created directory?

10
  • 3
    Why not leave the directory alone and just delete its contents? Mar 27 at 18:45
  • 1
    Exactly, can you explain what your final objective is here? If we know why you want this, we might be able to offer an alternative and we will certainly be able to help better since we will understand the aim. By the way, your second command isn't the same since rm -rf /some/path/.* wouldn't delete hidden files (e.g. /some/path/foo would remain) and, anyway, the second command would delete everything in any case, so it's pointless to run the first part before.
    – terdon
    Mar 27 at 18:59
  • Oh, and please tell us what operating system you are using so we know what tools you have available.
    – terdon
    Mar 27 at 19:00
  • 1
    Probably what you want here is cd path/to/somefolder && find . -delete which wipes all contents of somefolder but leaves somefolder itself in place. But that's not exactly what you asked for.
    – Wildcard
    Mar 27 at 19:27
  • 1
    @terdon mindepth isn't POSIX, not as portable.
    – Wildcard
    Mar 28 at 14:54

2 Answers 2

2

This is pretty easy to do using mtree.

Given a path a/ rooted in the current directory:

235158  1 drwx------    3 jim     wheel   4 Apr  1 08:08 .
235199  1 drwxr-xr-x    3 jim     wheel   3 Apr  1 08:05 ./a
234526  1 drwxr-xr-x    3 jim     wheel   3 Apr  1 08:05 ./a/b
234527  1 drwxrwxr-x    3 jim     wheel   3 Apr  1 08:05 ./a/b/c
234528  1 drwx------    2 jim     wheel   2 Apr  1 08:05 ./a/b/c/d

First create a heirarchy specification using mtree. -d means only process directories, -c is the flag to create a spec and write it to stdout, and -p a tells mtree where the heirarchy is rooted:

$ mtree -dcp a > a.mtree

Next, destroy the heirarchy in a and re-create an empty directory a:

$ rm -rf a
$ mkdir a

Finally, re-populate the directory heirarchy under a and set all the permissions to the values that were recorded in the initial specification created by mtree. Here we'll omit the -c flag because we're not creating a specification, we're reading it on stdin and comparing it to the actual heirarchy on disk. -t is added so that the timestamps within the heirarchy will be set to the values in the specification.

$ mtree -utp a < a.mtree 
.:      modification time (Mon Apr  1 08:05:24 2024, Mon Apr  1 08:11:33 2024, modified)
b:      modification time (Mon Apr  1 08:05:24 2024, Mon Apr  1 08:11:33 2024, modified)
b/c:    modification time (Mon Apr  1 08:05:24 2024, Mon Apr  1 08:11:33 2024, modified)
b/c/d:  modification time (Mon Apr  1 08:05:24 2024, Mon Apr  1 08:11:33 2024, modified)
$ find a -ls
235555  1 drwxr-xr-x   3 jim     wheel    3 Apr  1 08:05 a
194841  1 drwxr-xr-x   3 jim     wheel    3 Apr  1 08:05 a/b
194842  1 drwxrwxr-x   3 jim     wheel    3 Apr  1 08:05 a/b/c
194843  1 drwx------   2 jim     wheel    2 Apr  1 08:05 a/b/c/d

If you have write permission on a/ but not the parent directory where a/ is rooted, you could instead create a.mtree under /tmp and otherwise proceed similarly:

$ mtree -dcp a > /tmp/a.mtree
$ rm -rf a
rm: a: Permission denied

Despite the error message, everything except a/ itself is gone:

$ find a
a

So in the case where you don't have write permission to a/.., you can save a step by skipping the mkdir a. Continue:

$ mtree -utp a < /tmp/a.mtree 
.:      modification time (Mon Apr  1 08:05:24 2024, Mon Apr  1 08:11:33 2024, modified)
b:      modification time (Mon Apr  1 08:05:24 2024, Mon Apr  1 08:11:33 2024, modified)
b/c:    modification time (Mon Apr  1 08:05:24 2024, Mon Apr  1 08:11:33 2024, modified)
b/c/d:  modification time (Mon Apr  1 08:05:24 2024, Mon Apr  1 08:11:33 2024, modified)
1

Instead of deleting the directory and recreating it, consider just removing the contents and leaving the now-empty directory in place. This has the advantage of working when you're unable to write to the parent directory.

Alternatively, create the new directory before deleting the old one, so you can copy permissions (and perhaps even timestamps), e.g. using coreutils chmod --reference= and similar. Use mv to change the name of the new directory after removing the old (or to change the name of the old one before creating the new).

Not the answer you're looking for? Browse other questions tagged .