1 Example
$ tree .
.
├── dir1
├── dir2
├── dir3
├── dir4
└── dir5
$ find . -name dir1 -exec rm -rf {} \;
find: ‘./dir1’: No such file or directory
$ ls
dir2 dir3 dir4 dir5
The directory "./dir1" was removed, however, a warning message was printed.
2 Explanation
Below is the action steps find did:
- searched the folder ./dir1
- "rm -rf ./dir1"
- tried to enter "./dir1/" to find other folders named "dir1"
- ...
Here is the problem, even though "./dir1" was removed, find was NOT aware of this and still tried to enter the non-existing-anymore folder.
The reason for such a behavior is that find cannot identify "rm -rf" as a command to delete a folder. Actually, this is reasonable. The users may remove a folder with different command/script names; it's impossible for find to know all about it.
3 Solutions
3.1 Ignore it
Even find printed the error message, folder "./dir1" was removed as expected. So it's safe to ignore the messages.
$ find . -name dir1 -exec rm -rf {} \; 2>/dev/null
But this is not perfect as it also put other useful error messages into /dev/null. For example, "rm -rf ./dir1" may fail due to insufficient permissions, but you cannot see the errors with this command line.
3.3 use "-depth"
The '-depth' option indicates "deep first" algorithm, which changes the workflow as below:- searched the folder ./dir1
- Enter "./dir1/" to find other folders named "dir1" and remove it
- "rm -rf ./dir1"
- ...
$ find . -depth -name dir1 -exec rmdir {} \;
To illustrate more, we created another folder "./dir1/dir1" and checked the workflow.
$ find . -name dir1 -exec ls -d {} \;./dir1./dir1/dir1$ find . -depth -name dir1 -exec ls -d {} \;./dir1/dir1./dir1
- searched the folder ./dir1
- Enter "./dir1/" to find other folders named "dir1" and remove it
- "rm -rf ./dir1"
- ...
$ find . -name dir1 -exec ls -d {} \;
./dir1
./dir1/dir1
$ find . -depth -name dir1 -exec ls -d {} \;
./dir1/dir1
./dir1
It's clear that with '-depth', subfolders are handled before their containing folders.
3.2 use "-delete"
Fortunately, find has a built-in function to remove files/folders.
$ find . -name dir1 -delete
"-delete" actually implicitly applies "-depth".
What's better is that '-delete' works just like "rm -rf", so it can remove both folders and files.
3.4 use "-maxdepth 1" (preferred)
With "-maxdepth 1", find will NOT enter subfolders at all.
$ find . -maxdepth 1 -name dir1 -exec rm -rf {} \;
$ find . -maxdepth 1 -name dir1 -exec ls -d {} \;
./dir1
This would decrease the items that find to search, so the performance would be improved if many subfolders exist.
No comments:
Post a Comment