9

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 {} {}~ \;).

Baba
  • 3,279
t-bltg
  • 275

1 Answers1

10

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.

Wildcard
  • 36,499