Linux – Use find and do command on filename without “./” prefix

bashcommand linefindlinuxstring manipulation

Performing a cp on filenames in multiple subdirectories and prefix them with foo- leads to an error:

$ find my-dir -path "*/*" -execdir sh -c 'cp {} foo-{}' \;
cannot create regular file ‘foo-./blabla.jpg’: No such file or directory

On macOS I don't get this ./ prefix and the command works fine.

Is there a way to cp the filename without the ./ prefix?

Best Answer

Even if elsewhere your command works fine, it's still flawed. Never embed {} in the shell code.

The right approach is:

find my-dir -path "*/*" -execdir sh -c 'cp -- "$1" "foo-${1#./}"' sh {} \;

where ${1#./} is responsible for removing the leading ./ (if any). Note I used double dash, which is unnecessary (yet harmless) when find generates names with the ./ prefix, but useful otherwise.

Notes:

  • The command doesn't check if the matching whatever is a file. You will get a warning from cp if it's a directory.
  • The command doesn't check if foo-whatever exists and what it is. If it exists then you will get different results depending on whether it's a file or directory; and depending on if it's processed before or after whatever.
Related Question