Home > Software engineering >  Is there a way to perform echo | tee during find -exec?
Is there a way to perform echo | tee during find -exec?

Time:10-26

I have a problem with a code similar to the following:

function echotee() { echo $1 | tee -a ${FILE}; }
export -f echotee

find . -delete -exec sh -c 'echotee "Deleting: {}"' \;

The function echotee usually works as expected. However, during the -exec it does not. Indeed, it just prints on the terminal, omitting tee.

Hoping the question is not too trivial, thanks in advance.

CodePudding user response:

Why don't you just use this:

find . -delete -exec sh -c 'echo "Deleting: $1" | tee -a "$2"' _ {} "${FILE}" \;

No need to define and call a function.


You mentioned in a comment that you want to use echotee as a central point to print and log information. Have you considered a setup like this instead:

#!/usr/bin/env bash

# Send all script output to console and logfile
LOGFILE="..."
exec > >(tee -ia "${LOGFILE}") 2>&1

find . -delete -printf "Deleting: %f\n"

or this:

#!/usr/bin/env bash

# Set up fd 3 to send output to console and logfile on demand
LOGFILE="..."
exec 3> >(tee -ia "${LOGFILE}")

find . -delete -printf "Deleting: %f\n" 1>&3 2>&1

CodePudding user response:

  1. Use name() instead of function name().
  2. You did not set nor export FILE variable.
  3. sh does not support exporting functions. It's a feature of bash, you have to call bash.
  4. sh -c ' .... "{}"' will break on filenames containing " character. Put it as positional argument and use $1.
  5. $1 and $FILE expansions are not quoted and are subject to word splitting and filename expansion.
  6. echo $1 will break on filenames like -e. Prefer printf.
  7. Check your scripts with shellcheck - it will catch many such mistakes.

I think you meant to:

FILE=/tmp/log.txt
echotee() { printf "%s\n" "$1" | tee -a "$FILE"; }
export -f echotee
export FILE
find . -exec bash -c 'echotee "Deleting: $1"' -- {} \;

But the version from Shawn with -printf "Deleting: %p\n" | tee "$FILE" looks just nicer.

I think spawning tee and pipe will be slower then, I think doing like so could be a bit faster:

echotee() { printf "%s\n" "$1" >> "$FILE"; printf "%s\n" "$1"; }

or like:

exec 10>>"$FILE"
echotee() { printf "%s\n" "$1" >&10; printf "%s\n" "$1"; }

You could remove the pipe either way, just:

echotee() { tee -a "$FILE" <<<"$1"; }
  •  Tags:  
  • bash
  • Related