Basically, I have a folder /test/ that has a number of files of type .doc and .pdf. Some of the files have a .pdf and a .doc version, such as test.doc and test.pdf while others only have one version.

What I'm trying to do is find occurrences where there is a .doc and delete the corresponding .pdf using a script.

I've been tinkering with this line of code:

find /test/ -name "*.doc" - exec basename {} .doc \; -exec rm {}.pdf \;

However this returns the error that it cannot find files named example.doc.pdf instead of deleting the appropriately named .pdf from the find command. The reason I'm trying to do it this way is because there are .pdf files which don't have a matching .doc file which I do not wish to delete.

2 Answers 2


You can use this find command:

find /test/ -name "*.doc" -exec sh -c 'a="$1"; rm "${a%.doc}.pdf"' find-sh {} \;

It will search for .doc files in the directory /test/. For each found file a shell sh is called with the file as argument. ${a%.doc}.pdf replaces the file extension .doc with .pdf and rm removes it, if the file exists.

  • What does the find-sh part do? I'm tracking with everything but that part and how $1 in the sh call ends up holding the filename.
    – Wildcard
    Oct 13, 2015 at 15:34
  • @Wildcard $1 is the first argument given to the script by {} at the end which holds the filename. This is stored in a variable $a to do variable substitution. find-sh is just the name I gave the script. It can be anything.
    – chaos
    Oct 13, 2015 at 16:14
  • I see...am I correct in my understanding that you could omit find-sh and change the $1 to $0 and it would still work?
    – Wildcard
    Oct 13, 2015 at 18:27
  • @Wildcard No, $0 is the filename of the current script, not an argument.
    – chaos
    Oct 13, 2015 at 18:41
  • 1
    @Wildcard As I have written $0 is for the inline script name which is used for instance when displaying error messages. In the above example it contains find-sh. It becomes relevant when you call find with -exec sh -c '...' find-sh {} + (notice the +), because then "$@" contains the list of the arguments $1, $2, ..., without $0. So, in the above example it might work with $0, but keep that in mind.
    – chaos
    Oct 14, 2015 at 5:39

Save the following script as rm_dub.sh


rm_dub() {
    dir=$(dirname -- "$1")
    base=$(basename -- "$1" "$2")

    rm -- "$dir/$base$3"

rm_dub "$@"

and uses it with

find /test/ -name "*.doc" -exec sh rm_dub.sh {} .doc .pdf \;
  • I like the script but where does the actual deleting occur?
    – Wildcard
    Oct 13, 2015 at 15:31
  • @Wildcard added the rm Oct 13, 2015 at 15:44

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .