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
Memory Access Error Sys_Rt_Sigaction (Signal Handler)
Bash Shell Script Variable Assignment
Specifying Non-Standard Baud Rate for Ftdi Virtual Serial Port Under Linux
How to Get Multi-Line String Between Two Braces Containing a Specific Search String
Symbolic Link: Find All Files That Link to This File
Linux Command (Like Cat) to Read a Specified Quantity of Characters
How to Upgrade Openssl in Centos 6.5/Linux/Unix from Source
How to Fix the Rust Error "Linker 'Cc' Not Found" for Debian on Windows 10
Cmake:Set Environment Variables from a Script
Redirect Standard Input Dynamically in a Bash Script
Set Max_Execution_Time in PHP Cli
.Net-Core: Equivalent of Ildasm/Ilasm
X Keypress/Release Events Capturing Irrespective of Window in Focus