I have a mess in my photo libary. I have files like these:
image-1.jpg
image-1.jpeg
image-2.jpg
Now I want to delete all photos with the extension .jpeg when there is a file with the same name but with the extension .jpg.
How can I do this?
I have a mess in my photo libary. I have files like these:
image-1.jpg
image-1.jpeg
image-2.jpg
Now I want to delete all photos with the extension .jpeg when there is a file with the same name but with the extension .jpg.
How can I do this?
for f in *.jpeg; do
[ -e "${f%.*}.jpg" ] && echo rm -- "$f"
done
(remove echo
if happy).
With zsh
and one rm
invocation:
echo rm -- *.jpeg(e'{[ -e $REPLY:r.jpg ]}')
(change *
to **/*
to do that recursively, add the D
glob qualifier, if you also want to consider hidden files or files in hidden directories).
echo
... just examine the script output, and if happy, rerun the script and pipe to sh
!
– Jim L.
May 08 '19 at 21:06
${parameter%word}
shell parameter expansion (and -e
test).
– August Janse
Feb 03 '21 at 13:35
echo
won't output the right code in the sh language (unless none of the file names contain characters special in the sh language). You'd need zsh and print -r rm -- ${(qq)f}
for that.
– Stéphane Chazelas
May 06 '22 at 11:46
An adaption of an answer to a similar question:
find . -type f -name '*.jpeg' -exec sh -c '
for pathname do
jpg_pathname=${pathname%.jpeg}.jpg
if [ -f "$jpg_pathname" ]; then
printf "Would remove %s\n" "$pathname"
# rm "$pathname"
fi
done' sh {} +
This finds the pathnames of all files with a .jpeg
filename suffix in or below the current directory. For as large batches as possible of these pathnames, a short in-line script is called. The script loops over the current batch of pathnames and detects any file that has the same filename stem followed by .jpg
. If a .jpeg
file has a corresponding .jpg
file, the .jpeg
file is removed (if the commented out rm
is activated).
Shorter version (with safety comment removed and no text output):
find . -type f -name '*.jpeg' -exec sh -c '
for pathname do
[ -f "${pathname%.jpeg}.jpg" ] && rm "$pathname"
done' sh {} +
(You will notice that this turned out as a recursive variation of Stéphane Chazelas' answer)
readonly path="${1:-./}"
for file in "${path}"*.jpeg; do
if [[ -f ${file%.jpeg}.jpg ]]; then
rm -- "$file"
printf '%s\n' "removed duplicate file ${file}"
fi
done
The readonly variable at the top let's you pass the path to the directory as an arg to the script. It defaults to the current dir if no arg is given.
It simply loops through all files ending with '.jpeg' in the dir specified by the var path. Then it strips the extension and tests if the same file exists with a .jpg extension. If the .jpg dup exists, then the .jpeg file is considered the dup, and it is removed.
Current answers answer the specific case in the question body, but for the case of deleting all other files, I combined Stéphane Chazelas's answer with this answer on excluding glob matches:
shopt -s extglob
for f in .jpeg; do
[ -e "$f" ] && echo rm -- "${f%.}".!(jpeg)
done