bashsh

Using find's {} placeholder with -execdir in multiline bash commands


I'm trying to process directories using find with -execdir and create tar archives, but I'm having trouble with the {} placeholder in multiline commands.

What works:

When I use a simple one-liner, the placeholder works as expected:

find "$SOURCE" -mindepth 1 -maxdepth 1 -type d -execdir sh -c 'DIR="{}";echo $DIR' \;

This correctly outputs:

./2007_10_03 Event1
./2007_10_12 Event2

What doesn't work:

When I try to use the same approach in a multiline command with triple quotes, it fails:

find "$SOURCE" -mindepth 1 -maxdepth 1 -type d \
  -execdir sh -c """

DIR="{}"
echo $DIR

""" \;

This produces errors:

sh: line 2: Event1: command not found
sh: line 2: Event2: command not found

My goal:

I want to iterate through folders in $SOURCE and create a tar archive of each folder in $TARGET if the archive doesn't already exist. I need to capture the directory name from the {} placeholder to use in my script.

How can I properly use the {} placeholder in a multiline -execdir command? Why does my approach fail, and what's the correct way to handle this?


Solution

  • Like this:

    find "${SOURCE:?}" -mindepth 1 -maxdepth 1 -type d -exec sh -c '
        dir="$1"
        echo "$dir"
    ' sh {} \;    
    

    This is most readable and safer than using {}

    ${SOURCE:?} is a special parameter expansion that test if the variable exists. If not, find will not be executed, and you will have an error like:

    bash: SOURCE: parameter null or not set