0

Let's say I have a list of nested directories that looks like this:

./x1/mf/dir1
./x1/mf/dir2
./x1/mf/file1
./x2/mf/dir3
./x2/mf/file2
...

I want to remove all the subdirectories of every mf directory. Meaning dir1, dir2, dir3 in the previous example.

I know that

find . -type d -name "mf"

will return a list of all the directories called mf. And ls -d */ returns all the subdirectories in the current directory. So I tried

find . -type d -name "mf" -exec ls -d /* {} \;

to list the desired directories, but it would actually print the directories inside /. I was planning to pipe the resulting list to xargs rm -r to do the removal afterwards.

1
  • try find . -type d -path '*/mf/*' and then add -exec rm -r {} +.... Commented May 16, 2017 at 16:07

2 Answers 2

2

Setting up test directories and files:

$ mkdir -p x{1..3}/mf/dir{1..3}
$ touch x{1..3}/mf/file{1..3}
$ tree
.
|-- x1
|   `-- mf
|       |-- dir1
|       |-- dir2
|       |-- dir3
|       |-- file1
|       |-- file2
|       `-- file3
|-- x2
|   `-- mf
|       |-- dir1
|       |-- dir2
|       |-- dir3
|       |-- file1
|       |-- file2
|       `-- file3
`-- x3
    `-- mf
        |-- dir1
        |-- dir2
        |-- dir3
        |-- file1
        |-- file2
        `-- file3

Then find all directories that has mf in its path and delete them. The -depth does a depth-first traversal, so that find doesn't try to enter directories that it has already deleted. We also print the names of all directories that are deleted.

$ find . -depth -type d -path "*/mf/*" -print -exec rm -rf {} +
./x1/mf/dir1
./x1/mf/dir2
./x1/mf/dir3
./x2/mf/dir1
./x2/mf/dir2
./x2/mf/dir3
./x3/mf/dir1
./x3/mf/dir2
./x3/mf/dir3

Now:

$ tree
.
|-- x1
|   `-- mf
|       |-- file1
|       |-- file2
|       `-- file3
|-- x2
|   `-- mf
|       |-- file1
|       |-- file2
|       `-- file3
`-- x3
    `-- mf
        |-- file1
        |-- file2
        `-- file3
4
  • Which destro are you using? I tried the command on Ubuntu and got: find: warning: the -d option is deprecated; please use -depth instead, because the latter is a POSIX-compliant feature. find: paths must precede expression: . with no output. (I can't get the comment formatting right :P ) Commented May 17, 2017 at 16:39
  • @ditek This happened to be specific to the find on OpenBSD, but I have updated the answer to work with GNU/POSIX find too. Commented May 17, 2017 at 16:42
  • It works now, thanks. I was wondering about the + at the end of the command. I usually use ';'. Is there any difference? Commented May 17, 2017 at 16:51
  • The difference is that with \; the rm would be executed once for each found directory, while with + it would be executed once with as many directories as possible (if there were thousands, several rm runs would still be done, but not once per directory). Commented May 17, 2017 at 16:57
0

I strongly suggest using this to ls before rm -fring for obvious reasons:

find . -type d -name "mf" -print0 | xargs -0 -n1 -I haystack find haystack -type d -exec rm -fr {} \;

Example:

$ tree
.
├── bar
│   ├── foo
│   │   ├── bar
│   │   └── baz
│   └── freeble
├── baz
│   ├── foo
│   │   ├── bar
│   │   └── baz
│   └── freeble
└── quux
    ├── foo
    │   ├── bar
    │   └── baz
    └── freeble

15 directories, 0 files
$ find . -type d -name "foo" -print0 | xargs -0 -n1 -I haystack find haystack -type d -maxdepth 0 -exec rm -fr {} \;
$ tree
.
├── bar
│   └── freeble
├── baz
│   └── freeble
└── quux
    └── freeble

6 directories, 0 files
6
  • why not just find . -type d -name "mf" -exec rm -rf {} \;? Also, in your example you use foo and bar, but your suggestion does not. The solution you propose and the example you give should be consistent. Commented May 16, 2017 at 16:11
  • @Centimane Only the subdirectories of the mf directories were to be deleted, not the files of the mf directories. Commented May 16, 2017 at 16:19
  • Your example swaps mf with foo, and the directory foo was deleted. Commented May 16, 2017 at 16:29
  • Still begs the question why you didn't take the simpler: find . -type d -name "mf" -exec rm -rf {}/* \; Commented May 16, 2017 at 16:30
  • 1
    @Kusalananda my mistake! Commented May 16, 2017 at 16:31

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.