Contents
System environment Ubuntu 16.04.3 LTS
When writing a batch of docker image scripts, first copy the code directory to the corresponding directory where the image is created, then traverse the image directory to execute the build, make the image, and after the image build is completed, delete the code directory and delete the code directory. Find -exec combination command, but reported:
No such file or directory
Scene simulation:
zzfdeMacBook-Air:temp zzf$ mkdir testaaa zzfdeMacBook-Air:temp zzf$ ls | grep testaaa testaaa zzfdeMacBook-Air:temp zzf$ find . -type d -name "testaaa" -exec rm -r {} \; find: ./testaaa: No such file or directory
Find the testaaa directory again and find that the testaaa directory has indeed been deleted. But why would you report: No such file or directory?
zzfdeMacBook-Air:temp zzf$ ls testaaa ls: testaaa: No such file or directory
After checking the information of find, it is found that the default is recursive lookup. When executing the above combined command to delete the directory, it will traverse the testaaa directory. The actual execution process is as follows:
- Query all directories under the current directory
- Perform pattern matching ‘testaaa’, match successfully? success.
- Command after executing exec: rm -r testaaa
- Find tries to enter the testaaa/ directory, find the directory or file, and execute the command after exec
- Find does not find the testaaa directory, returns ENOENT (No such file or directory)
There are many solutions, and only the common methods are listed below:
1. Use find’s -maxdepth OPTIONS:
-maxdepth levels: Specifies the maximum directory depth for the actions of tests and actions, which can only be non-negative integers. It can be easily understood as the depth of directory search, but it is not. The current path directory has a level of 1, so if you specify -maxdepth 0 you won't get any results.
zzfdeMacBook-Air:temp zzf$ ls -d testaaa testaaa zzfdeMacBook-Air:temp zzf$ zzfdeMacBook-Air:temp zzf$ find . -maxdepth 1 -type d -name "testaaa" -exec rm -r {} \; zzfdeMacBook-Air:temp zzf$ echo $? 0 zzfdeMacBook-Air:temp zzf$ ls -d testaaa ls: testaaa: No such file or directory
2. Use find’s -prune ACTIONS:
-prune: Do not enter the directory (tell find, do not look for subdirectories or files in the directory to be deleted), so it can be used to ignore directories, but will not ignore normal files. When -depth is not given, it always returns true. If -depth is given, it returns false directly, so -delete (implicit -depth) is not used with -prune.
zzfdeMacBook-Air:temp zzf$ ls -d testaaa testaaa zzfdeMacBook-Air:temp zzf$ find . -type d -name "testaaa" -prune -exec rm -r {} \; zzfdeMacBook-Air:temp zzf$ echo $? 0 zzfdeMacBook-Air:temp zzf$ ls -d testaaa ls: testaaa: No such file or directory
3. Use + (plus sign) as the terminator of the find command without using it; (semicolon)
+ and ; difference:
; is the find traversal once to execute the command after the exec, and + will split the file or directory found in the batch, the batch runs the command, so it will not return an error, and when the content is too much, + will reduce the CPU usage.
zzfdeMacBook-Air:temp zzf$ ls -d testaaa testaaa zzfdeMacBook-Air:temp zzf$ find . -type d -name "testaaa" -exec rm -r {} + zzfdeMacBook-Air:temp zzf$ echo $? 0 zzfdeMacBook-Air:temp zzf$ ls -d testaaa ls: testaaa: No such file or directory
Of course you can also use | (pipe) + xargs :
find . -type d -name "testaaa" | xargs rm -r
But when testaaa does not exist, executing this combination command will return a non-zero status code, which is not in line with my scenario.
Discussion about this post