Delete all files with the same name as the ones that end in `.part`
I want to find all files under the current directory that end in .part
and delete them, along with all files with the same name even the ones with different extension.
Is this correct?
find . -name '*.part' -exec sh -c 'base="$(basename "$1" .part)"; find . -name "$base*" -delete' sh {} \;
1 answer
It is incorrect for several reasons.
You did not restrict Find's depth
It will thus descend into subdirectories and delete matching files there too.
Easily solvable by adding -maxdepth 1
to each Find.
File names containing glob characters
This is an edge case scenario.
Consider this structure:
.
├── abc
├── abc.part
├── cde
└── c*e.part
The outermost Find will find
-
abc.part
, sobase=abc
and the innermost Find looks for files matching the globabc*
, which matches theabc
file. Good. -
c*e.part
, sobase=c*e
and the innermost Find looks for files matching the globc*e*
, which matches thecde
file. Bad, becausecde
does not containc*e
.
File names with extra characters
If you have abcde
and abc.part
files, the former will be deleted because it matches abc*
as should be clear from the previous case discussion.
This particular problem would be easily fixed by changing $base*
-> $base.*
.
Solutions
You only want to operate in the current directory, so why not
for f in *.part; do
rm "${f%.part}."*
done
Here it is crucial not to quote the *
, because we want it to act as a glob (and not literally).
${f%suffix}
is a special form of parameter expansion available in all POSIX shells. It means "remove suffix
from the expansion of f
". It looks cleaner than Basename and doesn't spawn an extra process.
For something more along the lines you suggested,
find . -maxdepth 1 -name '*.part' -exec sh -c 'rm "$(basename "$1" .part)".*' sh {} \;
But it looks considerably convoluted and -maxdepth 1
is not a POSIX specified option to Find, so you are also sacrificing portability. (It is possible to write the POSIX equivalent of -maxdepth 1
but it adds obscurity.)
0 comment threads