Redirect Standard Input Dynamically in a Bash Script

Redirect standard input dynamically in a bash script

First of all stdin is file descriptor 0 (zero) rather than 1 (which is stdout).

You can duplicate file descriptors or use filenames conditionally like this:

[[ some_condition ]] && exec 3<"$filename" || exec 3<&0

some_long_command_line <&3

Note that the command shown will execute the second exec if either the condition is false or the first exec fails. If you don't want a potential failure to do that then you should use an if / else:

if [[ some_condition ]]
then
exec 3<"$filename"
else
exec 3<&0
fi

but then subsequent redirections from file descriptor 3 will fail if the first redirection failed (after the condition was true).

bash function that either receives file name as argument or uses standard input

You can use this simple wrapper:

args=("$@")         # save arguments into an array
set -o noclobber nounset pipefail errexit
set -- "${args[@]}" # set positional arguments from array

my_wrapper() {
[[ -f $1 ]] && SHA1SUM "$1" || SHA1SUM
}

my_wrapper "$@"

Note that you can use:

my_wrapper PATH_TO_FILE

or:

echo -n "blabla" | my_wrapper

How to redirect only newest line of output to file dynamically?

Let's mock a program that prints a new artist / song title every few seconds with a shell function:

printsong() {
local i=0
while :; do
echo "artist - song $((++i))"
sleep 3
done
}

Now, we read from this function, and overwrite a file every time we get a new line:

printsong | while IFS= read -r song; do echo "$song" > output; done

output will now always contain the most recent line of output from printsong.

Redirect bash output to dynamic file name

Just concatenate $1 with the "team.csv".

#!/bin/bash
mdb-export 2011ROXBURY.mdb TEAM > "${1}team.csv"

In the case that they do not pass an argument to the script, it will write to "team.csv"

AWK: redirecting script output from script to another file with dynamic name

i think

awk -v MYVAR="somedinamicdata" '{print $0 >> (MYVAR "-SomeStaticText") }' 2procfile

should do it. String concatenation in awk is just put one after another.

Redirect the terminal dynamic output to a file

Redirecting I/O on the shell modifies the behavior of many applications. Use script to capture all of the output to the terminal without interference:

script
diskutil zerodisk disk2
exit

The output will be in a file named typescript. You can change that using script command-line arguments, e.g.,

script redirect.txt diskutil zerodisk disk2

The resulting redirect.txt will contain all characters sent to the terminal, including carriage returns.

bash script: use command output to dynamically create menu and arrays?

#!/usr/bin/env bash

# Read command output line by line into array ${lines [@]}
# Bash 3.x: use the following instead:
# IFS=$'\n' read -d '' -ra lines < <(lsblk --nodeps -no name,serial,size | grep "sd")
readarray -t lines < <(lsblk --nodeps -no name,serial,size | grep "sd")

# Prompt the user to select one of the lines.
echo "Please select a drive:"
select choice in "${lines[@]}"; do
[[ -n $choice ]] || { echo "Invalid choice. Please try again." >&2; continue; }
break # valid choice was made; exit prompt.
done

# Split the chosen line into ID and serial number.
read -r id sn unused <<<"$choice"

echo "id: [$id]; s/n: [$sn]"

As for what you tried: using an unquoted command substitution ($(...)) inside an array constructor (( ... )) makes the tokens in the command's output subject to word splitting and globbing, which means that, by default, each whitespace-separated token becomes its own array element, and may expand to matching filenames.

Filling arrays in this manner is fragile, and even though you can fix that by setting IFS and turning off globbing (set -f), the better approach is to use readarray -t (Bash v4+) or IFS=$'\n' read -d '' -ra (Bash v3.x) with a process substitution to fill an array with the (unmodified) lines output by a command.

redirecting to file from var

You can't put the "<..." in a variable, but you can put the parameter to it in a variable

Also, redirecting stdin from /dev/fd/0 is a no-op, because /dev/fd/0 is bash's stdin, which is what mysql would inherit by default.

so you can make this work by falling back to taking stdin from /dev/fd/0, which looks similar to James_R_Ferguson's answer, except that it uses /dev/fd/0 because using /dev/tty makes an assumption that bash's stdin is an actual terminal.

#! /bin/bash

if [ -n "$1" ]; then # note, I changed this to test for non-empty
redirect="$1"
else
redirect="/dev/fd/0"
fi3
mysql --host=a.b --port=3306 --user=me --password='!' -D DCVBase2 < "$redirect"


Related Topics



Leave a reply



Submit