Command Substitution in Find -exec – How to Use It

basenamefind

If I just use basename {} .txt, it will work:

find . -iname "*.txt" -exec basename {} .txt \;

It will just print xxx instead of ./xxx.txt

if I want use $(basename {} .txt) in the -exec option, it will fail:

find . -iname "*.txt" -exec echo "$(basename {} .txt)" \;

It will just print ./xxx.txt

How can I solve this problem? I hope I can use $(basename {} .txt) as parameters for other cmd. Do I have to do sh -c or pipe -exec basename {} \; with xargs?

Best Answer

Try:

find -iname "*.txt" -exec sh -c 'for f do basename -- "$f" .txt;done' sh {} +

Your first command failed, because $(...) run in subshell, which treat {} as literal. so basename {} .txt return {}, your find became:

find . -iname "*.txt" -exec echo {} \;

which print file name matched.

Related Question