0

I have directory with 6 subdirectories but I wish to delete subdirectories from only 3 of them, hence I used a for loop to 'cd' inside these 3 directories, but I want to delete the subdirectories at depth 2 (maxdepth, mindepth as 2) inside the 3 subdirectories. I was using a find command at base(base is one of the 3 sub-directories) but it will find the directories from depth 1 (which is expected)

my file structure is /a/b/c/d/e (a is one of the 3 directories I'm iterating over)

a part of he code is below where I would need help/guidance - find /a -mindepth 2 -maxdepth 2 -type d -mtime +30

this will output - ./b/c

So I do not wish to delete the directory /b and delete only directory c and below/inside depths

Is there a way to do this or I will HAVE to cd to the b directory?

3
  • I this a question on how -delete or rm operate? rm (or -delete) on a/b/c will only delete c and leave a/b untouched. It must however be a result of your search, als find will show the path. b would only be deleted, if the results showed ./b or a/b (i.e. b as the main result of the search).
    – FelixJN
    Nov 13, 2023 at 7:54
  • find /a ... .. " this will output - ./b/c" -- no, it won't, it'll output /a/b/c, etc. Besides, you might as well create some directory structure and test find ... -delete on it to see what actually gets deleted. mkdir -p /a/b/c/d could help.
    – ilkkachu
    Nov 14, 2023 at 16:34
  • @ilkkachu you are correct find /a will output the absolute path i.e. /a/b/c (considering i'm at ~), I had the output ./b/c because i was already in the directory /a and I had provided the command find . -mindepth 2 -maxdepth 2 -type d -mtime +30 Nov 22, 2023 at 8:16

3 Answers 3

0

You can modify the command to execute a rm -rf on the found directories, but you should be extremely careful as it can lead to data loss. Here's how to do it:

find /a -mindepth 2 -maxdepth 2 -type d -mtime +30 -exec rm -rf {} \;

As always, you should test the command with an echo first:

find /a -mindepth 2 -maxdepth 2 -type d -mtime +30 -exec echo "Deleting: {}" \;

This will print the directories it would delete, allowing you to verify the command's behavior before actually deleting anything.

EDIT: Is it something like this you're looking for? The command below is not destructive.

find /a -mindepth 2 -maxdepth 2 -type d -mtime +30 -exec sh -c 'cd "{}" && echo "Deleting contents of $(pwd)"' \;

This command IS DESTRUCTIVE!

find /a -mindepth 2 -maxdepth 2 -type d -mtime +30 -exec sh -c 'cd "{}" && rm -rf *' \;
5
  • My main concern is the part where I mention I do not wish the delete the b directory at depth 1 - which is included in the output of my find command Nov 13, 2023 at 6:36
  • @user16454406 Please see my edit.
    – telometto
    Nov 13, 2023 at 21:36
  • I think that last command will delete the contents of ./b/c but not the directory ./b/c itself which is what is being asked for. If {} is ./b/c then your original version (sh -c 'rm -r {}') will delete ./b/c but not ./b alone. That was already correct. The edit isn't necessary.
    – raf
    Nov 14, 2023 at 13:40
  • @user16454406 The b directory shouldn't appear in the output of your find command (without a subdirectory appearing as well) because it would be excluded by -mindepth 2. It's at mindepth 1.
    – raf
    Nov 14, 2023 at 13:59
  • Also embedding {} in the code argument of sh is very bad practice. It introduces command injection vulnerabilities Nov 22, 2023 at 8:53
0

Disclaimer: I'm the current author of rawhide (rh) (see https://github.com/raforg/rawhide)

Hi, With rawhide (rh) you can do:

rh -m2 -M2 -x 'rm -r %s' /a 'd && old(30*days)'

To check first:

rh -m2 -M2 -x 'echo rm -r %s' /a 'd && old(30*days)'

-m2 is the same as -mindepth 2.

-M2 is the same as -maxdepth 2.

-x ... executes the given shell command on each match.

%s is replaced by the matching filepath (like find's {}).

/a is a search path.

'd && old(30*days)' matches directories (d) that haven't been modified (entries added or deleted) in at least 30 days (old(30*days) or old(month)).

Note: Checking the mtime of a directory only considers each directory's own mtime, not the mtime of any of its contents. The same is true with find.

2
  • the mtime of a directory does get modified if its contents are modified, tested on my amazon linux machine Nov 22, 2023 at 8:34
  • 1
    @user16454406, the mtime of a directory is only modified when an entry is added, removed or renamed in that directory (not in subdirectories). If you modify a file within that directory without changing its name (and without a .swp or backup copy of the original being added as some text editors do), then the mtime of the directory is not modified. Nov 22, 2023 at 8:55
0

Thanks everyone for the useful inputs, I was able to replicate my question/issue on my personal machine.

I was able to achieve solution to my issue with below command - somecode... base2=$(pwd) i.e. /a find $base2 -mindepth 2 -maxdepth 2 -type d -mtime +30 | xargs rm -R this will output /a/b/c however as specified it will remove only the directory at depth 2 i.e. /c After the command run we are left with /a/b so works as per my requirement.

2
  • pwd is the command that prints the value of the $PWD variable. $(pwd) mangles it as it removes the trailing newline characters. $base2 mangles it even more as you forgot to quote it (unless you use a saner shell like zsh) and piping to xargs without using -print0/-0 does even more mangling as xargs's expected input format doesn't match the default output format of find. Should be find "$PWD" -mindepth 2 -maxdepth 2 -type d -mtime +30 -exec rm -rf {} +. Nov 22, 2023 at 8:51
  • In any case using thé full path of . instead of . is rather pointless and will only make it less efficient and less reliable. Nov 22, 2023 at 9:03

You must log in to answer this question.

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