Unix & Linux Stack Exchange
Q&A for users of Linux, FreeBSD and other Unix-like operating systems
Latest Questions
5
votes
2
answers
363
views
How to do indirect variable substitution in a GNU Makefile?
In the shell I can do ``` $ a=b b=c; eval echo \$$a c ``` How do I do the same with GNU Make's `$(eval)` function? ``` $ cat Makefile a=b b=c x:; echo {What goes here in order to get:} $ make c ```
In the shell I can do
$ a=b b=c; eval echo \$$a
c
How do I do the same with GNU Make's $(eval)
function?
$ cat Makefile
a=b
b=c
x:; echo {What goes here in order to get:}
$ make
c
Dan Jacobson
(560 rep)
Jun 30, 2025, 05:33 AM
• Last activity: Jun 30, 2025, 06:55 AM
0
votes
1
answers
93
views
In Bash 5.2+, is there a means to read the command currently being evaluated?
...that is to say, is there a means by which I can read the full command that's being evaluated AS it's happening? Here's a contrived example, but one I feel makes the question clear: ```shell function showOwnEvaluation { local evaluatingCommand=???? [[ "$evaluatingCommand" =~ ^showOwnEvaluation ]]...
...that is to say, is there a means by which I can read the full command that's being evaluated AS it's happening? Here's a contrived example, but one I feel makes the question clear:
function showOwnEvaluation {
local evaluatingCommand=????
[[ "$evaluatingCommand" =~ ^showOwnEvaluation ]] && echo "Original Function"
}
alias sOE='showOwnEvaluation'
$ showOwnEvaluation 123
# Output: Original Function
$ sOE 123
# Output:
Basically the ability to run echo "$(!-1)"
for the current, active command? A echo "$(!0)"
, if you will?
What I'd like to accomplish here is this: if I'm assigning the result of an expansion to a variable:
someVar=$(myFunc)
...I'd like to be able to alter the response from myFunc
*based on the name of the variable it's being set to*. I simply cannot figure out how to get the someVar=
portion of the expression, if, indeed, it's even possible to DO such a thing (without slapping a full emulation over the terminal and monitoring all of the I/O, of course).
I know this may seem like a nonsensical desire, here, but I actually do have a valid use-case. I'm just uncertain if it's even feasible.
NerdyDeeds
(123 rep)
Jan 26, 2025, 12:53 AM
• Last activity: Jan 26, 2025, 03:49 PM
339
votes
11
answers
901074
views
What is the "eval" command in bash?
What can you do with the `eval` command? Why is it useful? Is it some kind of a built-in function in bash? There is no `man` page for it..
What can you do with the
eval
command? Why is it useful? Is it some kind of a built-in function in bash? There is no man
page for it..
LanceBaynes
(41465 rep)
Oct 22, 2011, 08:02 PM
• Last activity: Jan 10, 2025, 05:40 PM
0
votes
1
answers
122
views
How to properly make eval safe?
I'm writing a shell script that changes its behavior based on the number of positional parameters passed # script.sh ```bash if [ $# -eq 1 ]; then if [ -f "$1" ]; then validate='validate <"$1"' else validate='validate <<<"$1"' fi else IFS=$'\n' validate="validate <<<'${*}'" fi eval "$validate" | pul...
I'm writing a shell script that changes its behavior based on the number of positional parameters passed
# script.sh
if [ $# -eq 1 ]; then
if [ -f "$1" ]; then
validate='validate <"$1"'
else
validate='validate <<<"$1"'
fi
else
IFS=$'\n'
validate="validate <<<'${*}'"
fi
eval "$validate" | pull_data
Both validate
and pull_data
are Bash functions that read from stdin and write to stdout
If the first case [ $# -eq 1 ]
, I believe the code is safe from injection. Since the string is single-quoted, parameter expansion only happens after eval is called. I can't think of a string that could result in code injection here.
## Issue
The problem arise with the else
condition. Here, each positional parameters is expanded into a new line. For example
./script.sh "string_with_'_in_its_name" "code injected'"
The quote inside one of the first parameter causes subsequent new parameters to be interpreted as commands. Similarly, this also results in an injection vulnerability:
./script.sh valid_input \''$(code injected)'\'
## Context
I'm using eval to avoid repeating the validate ... | pull_data
construct in every if condition. The real script has many more conditions, and using eval makes it more readable.
Any advice on how to refactor this script to avoid the injection issue while maintaining readability would be greatly appreciated!
killua148
(3 rep)
Jan 5, 2025, 06:46 PM
• Last activity: Jan 7, 2025, 09:18 AM
0
votes
1
answers
93
views
eval for pathnames from mkdir -p
I am writing a script to move around a bit of data, which I want to be able to create the parent directory to where I am sending my data, in order to do some renaming/cleaning of filenames I need to keep track of the newly created directories so I can change the permissions to the set input argument...
I am writing a script to move around a bit of data, which I want to be able to create the parent directory to where I am sending my data, in order to do some renaming/cleaning of filenames I need to keep track of the newly created directories so I can change the permissions to the set input argument.
Seeing as
mkdir -vp
can output the created directories it felt perfect, however, I am unable to dereference the quotes to be able to use the output, and eval
seems the only option. I am aware that I could probably just loop and check if each directory exist, but it seems wasteful when mkdir
outputs it already.
This is my code as of now:
readarray -t ndir < <(ssh myhost mkdir -vp foo/ | grep -oP "^mkdir: created directory\s+\K['\"].+['\"](?=$)" | sort -r)
eval ndir=("${ndir[@]}")
ssh myhost chmod 555 "${ndir[@]}"
EDIT: If foo
was a path with newlines, or other special character they will be quoted in $'..'
format, which is why I started using eval.
It is my understanding that eval
is as close to evil as you can come, but I don't see any viable and as convenient solution other than manually looping over and checking which parts of the path exist. Is there a safer, and alternative way?
Caesar
(25 rep)
Nov 21, 2024, 12:55 AM
• Last activity: Nov 23, 2024, 08:52 AM
1
votes
0
answers
19
views
While Loop Exits After Calling Function
I'm trying to do a `db` backup script using `Bash`. When adding a "Resume" feature to the script, I do the following loop calling defined functions to do step by step (depending on the .lock file contents). This is unexpected behavior since I have created a bunch of other scripts that follow the sam...
I'm trying to do a
db
backup script using Bash
.
When adding a "Resume" feature to the script, I do the following loop calling defined functions to do step by step (depending on the .lock file contents).
This is unexpected behavior since I have created a bunch of other scripts that follow the same logic on calling functions from a loop and they work correctly.
My guess is it has something to do with the ssh
command which is the difference throughout all the other scripts, but I just can't wrap my mind around it…
```
LOCK=restore.lock
SERVER_BACKUP_FILE_NAME="backup"
...
show_help()
{
...
}
while getopts i:h opt; do
case $opt in
i) COMPANY_ID=$OPTARG;;
h) show_help
esac
done
...
backup()
{
if [ ! -z $COMPANY_ID ]
then
log_echo "Creating company backup file from production..."
sleep 5
SOURCE_SERVER_IP=$(dig +short ${SOURCE_SERVER_HOST})
REMOTE_CMD="~/repository/scripts/database/backup.sh -i ${COMPANY_ID}; exit;"
ssh ${SOURCE_SERVER_USER}@${SOURCE_SERVER_IP} "bash -l -c '${REMOTE_CMD}'"
SERVER_BACKUP_FILE_NAME="backup_${COMPANY_ID}"
fi
sed "/\/d" -i ${LOCK}
}
download()
{
...
}
import()
{
...
}
# For some reason the backup() function breaks the while loop.
restore()
{
while IFS= read -r FUNC; do
eval $FUNC;
done > ${LOCK}
echo "download" >> ${LOCK}
echo "import" >> ${LOCK}
else
log_echo "Resuming..."
fi
# Calling main function that loops through the .lock file containing the function names
# to dynamically execute said functions.
restore
James
(111 rep)
Jul 19, 2024, 02:46 AM
• Last activity: Jul 19, 2024, 03:03 AM
0
votes
2
answers
136
views
Confusing results of eval + sed combination
I run a game from steam which starts with the game companies launcher app where I have to click another button to start the actual game. The game launcher is very slow, contains needless advertising, which I should not be forced to experience as I paid for the game in it's entirety, it is not a free...
I run a game from steam which starts with the game companies launcher app where I have to click another button to start the actual game.
The game launcher is very slow, contains needless advertising, which I should not be forced to experience as I paid for the game in it's entirety, it is not a free online game *paid for by advertising*, and it sends my telemetry to different servers around the world!
Someone provided some simple code in a community guide to bypass the launcher but I cannot get it to work for reasons that make no sense to me.
Their simple code is to put this command in steam's properties for the game which works for them and other users
eval $( echo “%command%” | sed -E “s#Launcher/dowser.exe#Cities2.exe#g” )
But nothing happens when I start the game in steam, it just exits after 30 seconds or so. So I added **tee** to the command to see what sed ouputs, like this
eval $( echo “%command%” | sed -E “s#Launcher/dowser.exe#Cities2.exe#g” | tee ~/foot.txt)
And foo.txt is empty, which makes no sense because if I run this command
eval $( echo “%command%” | foo.bash )
Which is this script
#/bin/bash
echo "$*" > ~/foo.txt
Then foo.txt has the expected command line received by bash on STDIN that sed should be receiving.
So then I ran the same sed command with the --debug switch and get this output in a log
SED PROGRAM:
s/Launcher\/dowser.exe/Cities2.exe/g
INPUT: 'STDIN' line 1
PATTERN: /home/user/.local/share/Steam/ubuntu12_32/reaper SteamLaunch AppId=949230 -- /home/user/.local/share/Steam/ubuntu12_32/steam-launch-wrapper -- '/home/user/.local/share/Steam/steamapps/common/SteamLinuxRuntime_sniper'/_v2-entry-point --verb=waitforexitandrun -- '/home/user/.local/share/Steam/steamapps/common/Proton 8.0'/proton waitforexitandrun '/home/user/.local/share/Steam/steamapps/common/Cities Skylines II/Launcher/dowser.exe'
COMMAND: s/Launcher\/dowser.exe/Cities2.exe/g
MATCHED REGEX REGISTERS
regex = 409-428 'Launcher/dowser.exe'
PATTERN: /home/user/.local/share/Steam/ubuntu12_32/reaper SteamLaunch AppId=949230 -- /home/user/.local/share/Steam/ubuntu12_32/steam-launch-wrapper -- '/home/user/.local/share/Steam/steamapps/common/SteamLinuxRuntime_sniper'/_v2-entry-point --verb=waitforexitandrun -- '/home/user/.local/share/Steam/steamapps/common/Proton 8.0'/proton waitforexitandrun '/home/user/.local/share/Steam/steamapps/common/Cities Skylines II/Cities2.exe'
END-OF-CYCLE:
/home/user/.local/share/Steam/ubuntu12_32/reaper SteamLaunch AppId=949230 -- /home/user/.local/share/Steam/ubuntu12_32/steam-launch-wrapper -- '/home/user/.local/share/Steam/steamapps/common/SteamLinuxRuntime_sniper'/_v2-entry-point --verb=waitforexitandrun -- '/home/user/.local/share/Steam/steamapps/common/Proton 8.0'/proton waitforexitandrun '/home/user/.local/share/Steam/steamapps/common/Cities Skylines II/Cities2.exe'
So sed is receiving the expected data from steam on STDIN, and the sed commandline script is producing the expected result, but inexplicably eval is not recieving the sed output or not executing it.
Then just to see what happens, I ran the same command again but chained the sed output from the debug log after the sed command, so the result and output from sed would be thrown away, and the appended command would be run, like this
eval $( echo “%command%” | sed -E “s#Launcher/dowser.exe#Cities2.exe#g” & /home/user/.local/share/Steam/ubuntu12_32/reaper SteamLaunch AppId=949230 -- /home/user/.local/share/Steam/ubuntu12_32/steam-launch-wrapper -- '/home/user/.local/share/Steam/steamapps/common/SteamLinuxRuntime_sniper'/_v2-entry-point --verb=waitforexitandrun -- '/home/user/.local/share/Steam/steamapps/common/Proton 8.0'/proton waitforexitandrun '/home/user/.local/share/Steam/steamapps/common/Cities Skylines II/Cities2.exe')
And the game successfully runs without the launcher!!!
I don't get it, why is eval not executing the sed output as the command, but does execute the command line that sed apparently does output when I chain it after the sed command?
The only downside to that execution was that steam does not recognize that the game has closed when I exit it, but I could live with that.
I am running on Ubuntu 23.10, using steam in X
nobody special
(103 rep)
Dec 11, 2023, 04:24 PM
• Last activity: Jan 28, 2024, 03:16 PM
4
votes
2
answers
16854
views
Handling long-options with getopts
I am parsing options with `getopts` but would like to handle long-options as well. print-args () { title="$1" ; shift printf "\n%s\n" "${title}: \$@:" for arg in "$@"; do (( i = i + 1 )) printf "%s |%s|\n" "${i}." "$arg" done } getopts_test () { aggr=() for arg in "$@"; do case $arg in ("--colour"|"...
I am parsing options with
getopts
but would like to handle long-options as well.
print-args ()
{
title="$1" ; shift
printf "\n%s\n" "${title}: \$@:"
for arg in "$@"; do
(( i = i + 1 ))
printf "%s |%s|\n" "${i}." "$arg"
done
}
getopts_test ()
{
aggr=()
for arg in "$@"; do
case $arg in
("--colour"|"--color") aggr+=( "-c" ) ;;
("--colour="*|"--color="*) aggr+=( "-c" "${arg#*=}" ) ;;
(*) aggr+=( "$arg" ) ;;
esac
done
print-args "print" "$@"
eval set -- "${aggr[@]}"
print-args "eval" "$@"
set -- "${aggr[@]}"
print-args "set" "$@"
local OPTIND OPTARG
local shortopts="C:"
while getopts "$shortopts" arg; do
case $arg in
("c") context="$OPTARG" ;;
(*) break ;;
esac
done
shift $(( OPTIND - 1 ))
}
But I wonder whether the use of set -- "${aggr[@]}"
is correct.
Or is the following (using eval
) more appropriate?
eval set -- "${aggr[@]}"
I have performed a test shown below. With eval, the string "Gunga Din" is split up, whereas with set -- "${aggr[@]}"
, it is being parsed correctly as a single string.
getopts_test -f -g 130 --colour="170 20" "Gunga Din"
print: $@:
1. |-f|
2. |-g|
3. |130|
4. |--colour=170 20|
5. |Gunga Din|
eval: $@:
1. |-f|
2. |-g|
3. |130|
4. |-c|
5. |170|
6. |20|
7. |Gunga|
8. |Din|
set: $@:
1. |-f|
2. |-g|
3. |130|
4. |-c|
5. |170 20|
6. |Gunga Din|
Then I ran another function that uses the non-GNU getopt
.
getopt_test ()
{
shortopts="Vuhv::H::w::e::n::l::C:"
shortopts="${shortopts}bgcrmo"
longopts="version,usage,help,verbosity::"
longopts="${longopts},heading::,warning::,error::"
longopts="${longopts},blu,grn,cyn,red,mgn,org"
opts=$( getopt -o "$shortopts" -l "$longopts" -n "${0##*/}" -- "$@" )
print-args "\$@:" "$@"
print-args "opts:" "$opts"
set -- "$opts"
print-args "set -- \"$opts\"" "$@"
eval set -- "$opts"
print-args "eval set -- \"$opts\"" "$@"
}
This resulted in the following
getopt_test --warning=3 "foo'bar" "Gunga Din"
$@:
1. |--warning=3|
2. |foo'bar|
3. |Gunga Din|
opts:
1. | --warning '3' -- 'foo'\''bar' 'Gunga Din'|
set -- "$opts"
1. | --warning '3' -- 'foo'\''bar' 'Gunga Din'|
eval set -- "$opts"
1. |--warning|
2. |3|
3. |--|
4. |foo'bar|
5. |Gunga Din|
As shown the result of getopt is a single entry with positional arguments re-arranged. This shows the need to use eval set -- "$opts"
to split the positional arguments in the opts
string into five entries for option parsing and processing.
Vera
(1363 rep)
Oct 30, 2021, 09:46 AM
• Last activity: Dec 18, 2023, 04:43 PM
0
votes
2
answers
564
views
eval: $? vs ${PIPESTATUS[@]} (bash)
In bash 5.0, I wish to capture the `${PIPESTATUS[@]}` of a piped command that is executed via `eval`. However, `eval` appears to mask `${PIPESTATUS[@]}`, but doesn't mask `$?` which is the equivalent to `${PIPESTATUS[-1]}`. Is there a way to extract `${PIPESTATUS[@]}` from the results of `eval`? App...
In bash 5.0, I wish to capture the
${PIPESTATUS[@]}
of a piped command that is executed via eval
. However, eval
appears to mask ${PIPESTATUS[@]}
, but doesn't mask $?
which is the equivalent to ${PIPESTATUS[-1]}
. Is there a way to extract ${PIPESTATUS[@]}
from the results of eval
? Appending something to the commandstring below like && array=( ${PIPESTATUS[@]} ) && export array
does not appear to work.
Am I correct in assuming from this that $?
is not simply ${PIPESTATUS[-1]}
?
My sample code (ran as root):
#!/usr/bin/env bash
#without eval, ${PIPESTATUS[@]} has two entries as it should.
apt-get install -y java-17-openjdk-amd64 2>&1 | tee -a ~/log
commandsPipestatus=( ${PIPESTATUS[@]} )
for status in ${commandsPipestatus[@]}; do
echo $status
done
echo ""
echo ""
#with eval, ${PIPESTATUS[@]} has one entry and is equal to $?
commandstring="apt-get install -y java-17-openjdk-amd64 2>&1 | tee -a ~/log"
eval "$commandstring"
commandsPipestatus=( ${PIPESTATUS[@]} )
for status in ${commandsPipestatus[@]}; do
echo $status
done
EDIT: Fixed a small technical correction in my original statement about PIPESTATUS. Also, based on the answers below, here are some clarifications:
- I'm using eval
because I'm building command strings programmatically and some of them may contain bash -c
... which run the command as different users.
- I looked at setting pipefail
and that may work sometimes though not always because sometimes I need to know the status of multiple steps in the pipe. If I could set set -o pipefail
and then unset it after that could work, but I'm not seeing how to unset pipefail
and I can't simply exit the subshell and then continue in a new one where pipefail
is not been set. How do I unset a shell option such as pipefail
?
- Is my above understanding of how to export an array that contains PIPESTATUS
incorrect? How can I simply export PIPESTATUS
from the eval
subshell?
EDIT 2: Thanks to the excellent answer marked below, my final decision was for the case where I am dynamically assembling command strings that include redirection (which is why I need eval), I would use set -o pipefail
and then after execution do set +o pipefail
.
I'm also re-researching best practices for executing dynamically built commands, as I have several years more bash experience since the last time I did. My use cases for eval
are:
1. Commands may contain bash -c
, so I can't use bash -c
to execute them
2. May contain redirection, such as >> log
3. The dynamical commands may also have arguments added to them for debugging purposes
As far as I can tell, I may be able to do things differently for 1, and for 3 I should be using things like set -x [command]
and trap
instead. I have yet to find a solution for 2.
jitter
(5 rep)
Oct 15, 2023, 06:29 AM
• Last activity: Oct 23, 2023, 06:47 AM
0
votes
1
answers
1103
views
Sanitize input that is used to update script
Looking at a bash-script that takes input from Git commit comment to update itself. Simplified: `script`: ```sh #!/bin/bash comment='' printf '%s\n' "$comment" upgrade_script() { # Download latest: curl -o updated_script https://path/to/file # Get comment: new_comment="$(curl https://path/to/comment...
Looking at a bash-script that takes input from Git commit comment to update itself. Simplified:
script
:
#!/bin/bash
comment=''
printf '%s\n' "$comment"
upgrade_script() {
# Download latest:
curl -o updated_script https://path/to/file
# Get comment:
new_comment="$(curl https://path/to/comment) "
# Update comment='' with new_comment:
sed -i "3,0 s/comment=''/comment='$new_comment'/" updated_script
}
Issue is if comment has characters that either breaks sed
or mangles
bash. E.g:
# that's all she wrote! => comment='that's all she wrote!
# use /need/ over /want/ => s/comment=''/'use /need/ over /want'/'
and then of course with the potential for both malicious but also unintended things like:
# Remove tmp files by: ' rm -r *;' => comment='Remove tmp files by: ' rm -r *;''
---
## Would this be enough to battle the issue?
Add this before the sed -i
command:
new_comment=$(
sed \
-e "s/'/'\"'\"'/g" \
-e 's/[&\\/]/\\&/g; s/$/\\/; $s/\\$//'<<< "$new_comment"
)
For bash
:
1) Replace '
with '"'"'
.
For sed
:
1) Escape &
, \
, /
and line-terminators.
or what would be the faults?
----
Ideally this would not be done at all but curious to know.
### *Side comment:*
Another solution, *to keep it in one file*, could be to add an exit
in the script and add the text after that, then use sed
or the like to print it. But that is beside my question.
#!/bin/bash
code
code
code
# When in need of the comment:
sed -n '/^exit # EOF Script$/$ {/start_xyz/,/end_xyz/ ...}'
# or what ever. Could even record offset and byte-length safely
code
code
exit # EOF Script
start_xyz
Blah blah blah
blaah
end_xyz
And thinking of it I guess something in the realm of:
comment=<<<'SOF'
...
SOF
Where one only need to replace any SOF
to not end prematurely. Still my question is the*sanitizing* above. Thanks.
Err488
(25 rep)
Jun 26, 2023, 06:59 PM
• Last activity: Jun 27, 2023, 06:02 AM
0
votes
1
answers
78
views
Shell script: Using variables makes command fails ( substituting values of variables manually ; command works fine )
In a bash script: jenkins_folder=`cut -d "|" -f1 -s input.csv` jenkins_url='https://url.com:8181/jenkins/view/' echo "jenkins_folder : ${jenkins_folder}" for job in `java -jar jenkins-cli.jar -s ${jenkins_url}${jenkins_folder} list-jobs ${jenkins_folder} ` do echo "Job name:: ${job} ****" java -jar...
In a bash script:
jenkins_folder=
cut -d "|" -f1 -s input.csv
jenkins_url='https://url.com:8181/jenkins/view/ '
echo "jenkins_folder : ${jenkins_folder}"
for job in java -jar jenkins-cli.jar -s ${jenkins_url}${jenkins_folder} list-jobs ${jenkins_folder}
do
echo "Job name:: ${job} ****"
java -jar jenkins-cli.jar -s ${jenkins_url}${jenkins_folder} get-job ${job} > job.xml
done
is giving following output
jenkins_folder : Platform-X.X.X-SPO-MyPD-Integration-Dummy
****ame:: NH-AccountManagementAudit-Consumer-MyPD-Integration-DUMMY-Reporting
'; perhaps you meant 'NH-AccountManagementAudit-Consumer-MyPD-Integration-DUMMY-Reporting'?
And when I substitute values of all variables and run following command; it works fine
java -jar jenkins-cli.jar -s https://url.com:8181/jenkins/view/Platform-X.X.X-SPO-MyPD-Integration-Dummy get-job NH-AccountManagementAudit-Consumer-MyPD-Integration-DUMMY-Reporting > job.xml
I have wasted too much time on this. I even tried using eval function but no luck. Please help.
Thanks to @Kusalananda when I am trying to echo job name its printing output in wierd fashion.. I feel this is the root cause.. but not sure why that is happening
If I try to shorten the length of variable job (using substring); then it prints fine. Hence, if value of job is long; it is creating problem
Deepak Singhal
(103 rep)
Apr 24, 2023, 10:55 AM
• Last activity: Apr 24, 2023, 12:21 PM
4
votes
4
answers
709
views
awk or perl to eval mathematical expressions in each line
I want a script to make awk to become an interactive mathematical calculator, to eval mathematical expressions given in each line. I.e., instead of constructing awk commands to calculate expressions like the following: ``` $ awk 'BEGIN{print 180/1149}' 0.156658 $ awk 'BEGIN{print (150+141)/1149}' 0....
I want a script to make awk to become an interactive mathematical calculator, to eval mathematical expressions given in each line.
I.e., instead of constructing awk commands to calculate expressions like the following:
$ awk 'BEGIN{print 180/1149}'
0.156658
$ awk 'BEGIN{print (150+141)/1149}'
0.253264
I want my script to take my mathematical expressions as input and do the calculation interactively. So the session will look like (alternative of input and output):
180/1149
0.156658
(150+141)/1149
0.253264
1 + 2
3
2 * 3 - 5
1
However I'm not able to do that myself:
$ awk '{print}'
180/1149
180/1149
^C
$ awk '{print $0}'
180/1149
180/1149
1 + 2
1 + 2
^C
If there is no simple solution to awk, what else, like perl?
xpt
(1858 rep)
Mar 24, 2023, 04:53 PM
• Last activity: Mar 25, 2023, 12:00 PM
1
votes
1
answers
1148
views
Command output evaluation not working in Bash script
I am trying to automate adding Homebrew to my path in a shell script, but these two lines do not evaluate inside my shell script: ```bash #!/bin/sh eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)" ``` The second line of code runs the program `[home]brew` with [the argument `shellenv`](https://...
I am trying to automate adding Homebrew to my path in a shell script, but these two lines do not evaluate inside my shell script:
#!/bin/sh
eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)"
The second line of code runs the program [home]brew
with [the argument shellenv
](https://github.com/Homebrew/brew/blob/master/Library/Homebrew/cmd/shellenv.sh) . It echoes several environment variables to set which are then evaluated. The first line just adds the second line to my ~/.profile
so brew
's PATH is setup in every shell.
I noticed that this statement does not work in my shell script, ***but*** it does when I type it into my terminal. What might be causing this?
I tried running the commands I was instructed to run after Homebrew installed in a shell script and got the same behavior.
**similar question:**
- [problem with homebrew installation path on linux](https://unix.stackexchange.com/questions/713835/problem-with-homebrew-installation-path-on-linux)
unrealapex
(132 rep)
Feb 16, 2023, 01:37 AM
• Last activity: Feb 19, 2023, 08:41 AM
-1
votes
1
answers
97
views
use a variable as a variable
I'd like to use a variable `variablenaam` for using in a loop. I tried for hours but can't make it work. My experiment in bash on a RPi 4 with the latest Raspbian. I like to make the use of xstack1 and xstack2 variable so i can use them in a loop. Example below has two stacks I like to use in a loop...
I'd like to use a variable
variablenaam
for using in a loop.
I tried for hours but can't make it work.
My experiment in bash on a RPi 4 with the latest Raspbian.
I like to make the use of xstack1 and xstack2 variable so i can use them in a loop. Example below has two stacks I like to use in a loop
so I have to make the variable xstack variable
.
clear
xstack1=( domoticz dashboard dashticz nodered )
xstack2=( x y z )
printf "Original value xstack1[*]= ${xstack1[*]}" # this gives all the entries of x, this must be the result at the end by choose for xstack1 = q=1
printf "\n\n Lets Start, try to make xstack variable"
q=1 # we want tot retrieve all values of xstack1
qq=$(eval "echo xstack${q}")
printf "\nvariablenaame of xstack1 = $qq" # so far so good
printf "\n"
qqq=$(eval "echo $qq[*]") #now add the all parameter
printf "\nvariablenaam with wildcard must do show all values but dont= $qqq" #only one value
printf "\n\n"
qqqq=$(eval "echo \$$qqq")
printf "last try and does not work, i only get one value= ${qqqq}\n"
This is The code where i want to use it. you see for similar block with stack1-4 and i think this can be one block with a variable name for xstack1-4. This xstack is a array and i think that gives the problem. These blocks are working perfectly, but not written perfectly :-)
local t_maxkolom=9
local t_mitem=1
local t_stack=0
while [ $t_stack -lt $t_maxkolom ]
do
local t_gitem=0
local t_sp='%31s'
if [ -z "${stack1[$t_stack]}" ]; then printf $t_sp && printf "${normal}"; else
printf "${number} $((t_mitem + $t_gitem )))${normal} Toevoegen " && printf '%-16s' "${stack1[$t_stack]}" && printf "${normal}"
fi
local t_sp='%32s'
local t_gitem=$((t_gitem + 10))
if [ -z "${stack2[$t_stack]}" ]; then printf $t_sp && printf "${normal}"; else
printf "${number} $((t_mitem + $t_gitem )))${normal} Toevoegen " && printf '%-16s' "${stack2[$t_stack]}" && printf "${normal}"
fi
local t_sp='%32s'
local t_gitem=$((t_gitem + 10))
if [ -z "${stack3[$t_stack]}" ]; then printf $t_sp && printf "${normal}"; else
printf "${number} $((t_mitem + $t_gitem )))${normal} Toevoegen " && printf '%-16s' "${stack3[$t_stack]}" && printf "${normal}"
fi
local t_sp='%32s'
local t_gitem=$((t_gitem + 10))
if [ -z "${stack4[$t_stack]}" ]; then printf $t_sp && printf "${normal}\n"; else
printf "${number} $((t_mitem + $t_gitem )))${normal} Toevoegen " && printf '%-16s' "${stack4[$t_stack]}" && printf "${normal}"
printf "\n"
fi
t_stack=$(( $t_stack + 1 ))
t_mitem=$((t_mitem + 1))
done
With this code I generate the menu items for my docker app

pvk
(5 rep)
Feb 11, 2023, 03:50 PM
• Last activity: Feb 15, 2023, 10:18 AM
0
votes
1
answers
397
views
Declare variable in eval Bash
There is a way to declare variable in eval ? For example function test { eval $1 } test " value="foo" echo "$value" " But it display nothing. Anyone can help please ?
There is a way to declare variable in eval ? For example
function test
{
eval $1
}
test "
value="foo"
echo "$value"
"
But it display nothing.
Anyone can help please ?
RevOneX9
(3 rep)
Dec 2, 2022, 01:03 AM
• Last activity: Dec 2, 2022, 01:25 AM
0
votes
0
answers
297
views
How does one store the evaluation of a big string with multiple env variables $VAR into another env variable?
Becuase [I need to make sure I run authentication for my nohup commands][1] I need the real command I want to run to be in a string in here: ``` nohup sh -c 'echo $SU_PASSWORD | /afs/cs/software/bin/reauth; python -u $RUN_CMD' > $PWD/nohup.out$SLURM_JOBID & ``` I tried creating the string and storin...
Becuase I need to make sure I run authentication for my nohup commands I need the real command I want to run to be in a string in here:
nohup sh -c 'echo $SU_PASSWORD | /afs/cs/software/bin/reauth; python -u $RUN_CMD' > $PWD/nohup.out$SLURM_JOBID &
I tried creating the string and storing it in the variable $RUN_CMD
e.g.
export RUN_CMD='${!HOME}/diversity-for-predictive-success-of-meta-learning/div_src/diversity_src/experiment_mains/main_diversity_with_task2vec.py --manual_loads_name diversity_ala_task2vec_delauny > $OUT_FILE 2> $ERR_FILE'
but I can't make it work. How do I do it? My attempts:
(metalearning_gpu) brando9~ $ export RUN_CMD='${!HOME}/diversity-for-predictive-success-of-meta-learning/div_src/diversity_src/experiment_mains/main_diversity_with_task2vec.py --manual_loads_name diversity_ala_task2vec_delauny > $OUT_FILE 2> $ERR_FILE'
(metalearning_gpu) brando9~ $ echo $RUN_CMD
${!HOME}/diversity-for-predictive-success-of-meta-learning/div_src/diversity_src/experiment_mains/main_diversity_with_task2vec.py --manual_loads_name diversity_ala_task2vec_delauny > $OUT_FILE 2> $ERR_FILE
(metalearning_gpu) brando9~ $ export RUN_CMD=$(echo '$HOME/diversity-for-predictive-success-of-meta-learning/div_src/diversity_src/experiment_mains/main_diversity_with_task2vec.py --manual_loads_name diversity_ala_task2vec_delauny > $OUT_FILE 2> $ERR_FILE')
(metalearning_gpu) brando9~ $ echo $RUN_CMD
$HOME/diversity-for-predictive-success-of-meta-learning/div_src/diversity_src/experiment_mains/main_diversity_with_task2vec.py --manual_loads_name diversity_ala_task2vec_delauny > $OUT_FILE 2> $ERR_FILE
(metalearning_gpu) brando9~ $ export RUN_CMD=$(echo '${!HOME}/diversity-for-predictive-success-of-meta-learning/div_src/diversity_src/experiment_mains/main_diversity_with_task2vec.py --manual_loads_name diversity_ala_task2vec_delauny > $OUT_FILE 2> $ERR_FILE')
(metalearning_gpu) brando9~ $ echo $RUN_CMD
${!HOME}/diversity-for-predictive-success-of-meta-learning/div_src/diversity_src/experiment_mains/main_diversity_with_task2vec.py --manual_loads_name diversity_ala_task2vec_delauny > $OUT_FILE 2> $ERR_FILE
(metalearning_gpu) brando9~ $ export RUN_CMD=(eval '$HOME/diversity-for-predictive-success-of-meta-learning/div_src/diversity_src/experiment_mains/main_diversity_with_task2vec.py --manual_loads_name diversity_ala_task2vec_delauny > $OUT_FILE 2> $ERR_FILE')
(metalearning_gpu) brando9~ $ echo $RUN_CMD
eval
related:
- https://stackoverflow.com/questions/14049057/bash-expand-variable-in-a-variable
- https://unix.stackexchange.com/questions/341243/bash-perform-variable-expansion-of-string#:~:text=Bash%20uses%20the%20value%20of,is%20known%20as%20indirect%20expansion .
- https://unix.stackexchange.com/questions/341243/bash-perform-variable-expansion-of-string/341246?noredirect=1#comment1376474_341246
Charlie Parker
(1597 rep)
Nov 23, 2022, 09:13 PM
0
votes
2
answers
438
views
Bash: how to wrap a command to measure its elapsed time?
How to wrap a command to measure its elapsed time? Currently I do it using `eval`: ``` do_cmd_named() { local name=$1 local cmd=$2 echo "$name" local start_time=$(date +%s) eval "$cmd 2>&1" local exit_status=$? local end_time=$(date +%s) local elapsed_time_sec=$((end_time-start_time)) local elapsed_...
How to wrap a command to measure its elapsed time?
Currently I do it using
eval
:
do_cmd_named()
{
local name=$1
local cmd=$2
echo "$name"
local start_time=$(date +%s)
eval "$cmd 2>&1"
local exit_status=$?
local end_time=$(date +%s)
local elapsed_time_sec=$((end_time-start_time))
local elapsed_time_min_sec=$(date -ud "@$elapsed_time_sec" +'%M:%S')
if [[ $exit_status -ne 0 ]]
then
echo "$name failed with exit status $exit_status (elapsed time $elapsed_time_min_sec)"
return $exit_status
else
echo "$name done (elapsed time $elapsed_time_min_sec)"
fi
}
job()
{
sleep 1
}
do_cmd_named "do job" "job"
which leads to:
do job
do job done (elapsed time 00:01)
For my cases this approach _almost _ works. However, this approach is considered bad because it violates some rules from BashFAQ . For example, "don't put code inside variables" from [BashFAQ #50](https://mywiki.wooledge.org/BashFAQ/050) (see also [BashFAQ #48](https://mywiki.wooledge.org/BashFAQ/048)).
So, the question is: how to do it correctly?
pmor
(665 rep)
Nov 21, 2022, 09:22 AM
• Last activity: Nov 23, 2022, 04:28 PM
1
votes
1
answers
105
views
Bash - How to make dynamic menu selection without eval
I'm making a script for Docker environments, and I'm a bit stuck with a pigeonhole I've gotten myself into. #!/bin/bash set -euo pipefail # Variables gituser="modem7" gitrepo="docker-devenv" gitfolder="Environments" buildername="DockerDevBuilder" # Colours RED="\e[31m" GREEN="\e[32m" END="\e[0m" ech...
I'm making a script for Docker environments, and I'm a bit stuck with a pigeonhole I've gotten myself into.
#!/bin/bash
set -euo pipefail
# Variables
gituser="modem7"
gitrepo="docker-devenv"
gitfolder="Environments"
buildername="DockerDevBuilder"
# Colours
RED="\e[31m"
GREEN="\e[32m"
END="\e[0m"
echo "========================================="
printf " Checking Dependencies\n"
echo "========================================="
printf "Checking if dependencies are installed...\n"
pkg_list=(docker jq)
tc() { set ${*,,} ; echo ${*^} ; }
for pkg in "${pkg_list[@]}"
do
titlecase=$(tc $pkg)
isinstalled=$(dpkg-query -l $pkg > /dev/null 2>&1)
if [ $? -eq 0 ];
then
printf "~ $titlecase is...${GREEN}installed${END}\n"
else
printf "~ $titlecase is...${RED}not installed${END}\n"
printf "Exiting Script. Install $pkg.\n"
echo "========================================="
exit
fi
done
echo "========================================="
cat /dev/null 2>&1; then
echo ""
echo "Builder $buildername created"
else
echo "Builder already created, using $buildername"
docker buildx use "DockerDevBuilder"
echo ""
fi
echo "Creating $dev_name Environment..."
docker buildx build --rm=true --build-arg BUILDKIT_INLINE_CACHE=1 --load -t $lowerdev:dev https://github.com/$gituser/$gitrepo.git#:$gitfolder/$dev_name \
&& clear \
&& echo "=========================================" \
&& echo "Activating $dev_name Dev Environment..." \
&& echo "Press CTRL + D or type exit to leave the container" \
&& docker run --rm -it --name "$dev_name"Dev"$RANDOM" --hostname "$dev_name"Dev"$RANDOM" "$lowerdev:dev"
break
;;
"Prune")
echo "Clearing Docker cache..."
docker system prune -af
echo ""
echo "Removing Docker buildx builder..."
if docker buildx rm "$buildername" > /dev/null 2>&1; then
echo ""
echo "Builder $buildername removed"
else
echo "Builder already removed, no action performed"
echo ""
fi
exec bash $0
;;
"Quit")
echo "Exiting script"
exit
;;
*)
echo "invalid option $REPLY"
;;
esac"
done
exit 0
I'm currently using "
eval "case \"$dev_name\" in
" but that seems problematic from what I've read.
It works, but I'm not sure if there is a better way to achieve what the results.
The choices are created from the folder names in the repo , but I'm not quite sure how to get out of using eval. Am I worrying about something pointless?
Modem7
(11 rep)
Nov 3, 2022, 06:56 PM
• Last activity: Nov 4, 2022, 01:17 AM
0
votes
1
answers
1297
views
Using `env` command with `eval`
Suppose I have this in `script.sh`: ```bash env -i SOMEVAR=SOMEVALUE eval -- "$@" ``` I run it with: ```bash ./script.sh echo "\$SOMEVAR" ``` Now it shows: ```bash env: ‘eval’: No such file or directory ``` I suppose it doesn't work because `eval` is a Bash builtin. Any way to make `env` work with `...
Suppose I have this in
script.sh
:
env -i SOMEVAR=SOMEVALUE eval -- "$@"
I run it with:
./script.sh echo "\$SOMEVAR"
Now it shows:
env: ‘eval’: No such file or directory
I suppose it doesn't work because eval
is a Bash builtin.
Any way to make env
work with eval
?
sudoer
(65 rep)
Sep 12, 2022, 01:32 PM
• Last activity: Sep 12, 2022, 01:53 PM
20
votes
4
answers
66693
views
How can I list all user names and/or home directories?
I want to list all the users’ directories on the machine. Usually, I will do: ls -l /home But I use it in a script that will be deployed on others’ machines and maybe on those machines they don't call it home (e.g. myHome). So I want to generalize it to `ls -l ~`. But it just lists my user’s home di...
I want to list all the users’ directories on the machine. Usually, I will do:
ls -l /home
But I use it in a script that will be deployed on others’ machines and maybe on those machines they don't call it home (e.g. myHome).
So I want to generalize it to
ls -l ~
. But it just lists my user’s home directory instead of all users’ home directories (basically I want to get a list of the users’ names on the machine).
How can I generalize it?
lakerda
(355 rep)
Dec 7, 2017, 07:50 AM
• Last activity: Sep 5, 2022, 03:13 PM
Showing page 1 of 20 total questions