When using

$ find . -name string~ -exec cp {} FOO \;

is there a way to use {} in FOO to remove the tilde character as we usually do with bash substrings

e.g. :

 $ echo ${string%substring}

I aim to copy the files named string~ to string (the opposite of $ find . -name string -exec cp {} {}~ \;).

1 Answer 1


This is a case where you should stuff the code execution into a spawned shell.

find . -name '*~' -exec sh -c 'cp "$0" "${0%~}"' {} \;

This way you don't need to write a script. You just do it in a one-liner.

Note: You don't need the -- "end of options" specifier for cp here, because find will prefix the files found with ./, which will prevent them from being parsed as options to cp.

(The exception to this ./ prefix is if the current directory . is itself "found," but of course that name doesn't end with a tilde, nor could it be mistaken as an option flag.)

I would even use a spawned shell for appending a tilde to the copy's name; in other words I'd use:

find . -name string -exec sh -c 'cp "$1" "$1"~' find-sh {} \;

in preference to:

find . -name string -exec cp {} {}~ \;  # Don't use this!

as the latter is unspecified by POSIX and therefore unportable.

From the POSIX specifications for find:

If a utility_name or argument string contains the two characters "{}", but not just the two characters "{}", it is implementation-defined whether find replaces those two characters or uses the string without change.

... If more than one argument containing the two characters "{}" is present, the behavior is unspecified.

  • @StéphaneChazelas, aha, yes, I see—treatment of -- as an options terminator is guideline 10. Fixed answer.
    – Wildcard
    Nov 7, 2016 at 23:51

You must log in to answer this question.

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