Bash脚本中如何将输出重定向至代表标准流的变量(类Perl实现)
Perl makes it easy to abstract output targets with variables that handle both files and standard streams seamlessly. In Bash 4.2 on RHEL7, you can replicate this behavior with a couple of straightforward approaches—no need to rewrite your echo/printf calls every time you switch between stdout and a file.
Method 1: Using Custom File Descriptors (Best for Script-Wide Use)
This approach lets you set up a single "stream variable" once at the start of your script, then redirect all relevant output to it without repeating checks.
# Define your target: either a file path or "stdout" output_target="/tmp/my_output.txt" # output_target="stdout" # Uncomment this to switch to stdout # Link a custom file descriptor (here, fd 3) to your target if [[ "$output_target" == "stdout" ]]; then exec 3>&1 # Map fd 3 to the current stdout else exec 3>"$output_target" # Map fd 3 to the specified file (overwrites existing) # Use exec 3>>"$output_target" if you want to append instead of overwrite fi # Now redirect output to fd 3 anywhere in your script echo "This goes to the target (file or stdout)!" >&3 printf "Formatted output: %s\n" "works too" >&3 # Optional: Clean up the file descriptor when you're done with it exec 3>&-
Key Notes:
- File descriptors 3-9 are safe to use (0=stdin, 1=stdout, 2=stderr are reserved).
- This method is efficient for scripts with lots of output—you only check the target once.
- Use
>>instead of>in theexecline if you want to append to the file instead of overwriting it.
Method 2: Wrapper Function (Simple & Readable)
If you prefer a more explicit approach, wrap your output logic in a function that handles the target check for you each time.
# Define a function to send output to the target send_to_target() { local content="$1" local target="$2" if [[ "$target" == "stdout" ]]; then echo "$content" else echo "$content" > "$target" # Again, use >> instead of > to append fi } # Usage example output_target="stdout" # output_target="/tmp/another_output.log" send_to_target "First line of content" "$output_target" send_to_target "$(date +"[%Y-%m-%d %H:%M:%S] Log message")" "$output_target"
Key Notes:
- Great for scripts where you only need to send output a few times.
- You can extend the function to support printf by adding a flag or separate logic if needed.
Both methods let you treat your output target as a variable, just like you would in Perl—switch between stdout and a file by changing a single variable value, no need to modify every echo/printf call.
内容的提问来源于stack exchange,提问作者vesperto

