I have a file named countdown on my computer and I am trying to get it to countdown from what ever the user puts in.
for example ./countdown 5 would cause a 5 second timer to start outputting a "." every second and prints done after 5 seconds.
./countdown 10 would cause a 10 second timer to start outputting "." every second and prints done after 10 seconds.
here is my code, how can i read what the user inputs
t=$((5))
while [ $t -gt 0 ]; do
echo -ne "."
sleep 1
: $((t--))
done
echo "done"
Just change t=$((5)) to t=$1, which will assign the first argument to t.
Related
This question already has answers here:
Brace expansion with variable? [duplicate]
(6 answers)
Closed 3 years ago.
I need to get user input for a number and then write a name row by row in linux terminal that much amount of times that user inputed. Example if I lets say chose a number 2 the program will write Name 2 times row by row. I wrote some code but I cant figure where is the mistake. I think its the loop where the mistake is.
echo "Please enter a number "
read $number
for value in {$number}
do
echo "Name"
done
To read input and save it into a variable named number, do:
read number
To get the value of number, do $number or ${number}. Remove the { } in the {$number} or shift $ with {.
Just do:
echo "Please enter a number "
read number
if ! test "$number" -gt 0 2> /dev/null; then
echo "You must enter an integer greater than 0" >&2
exit 1
fi
yes Name | sed ${number}q
But don't prompt for the number. Take it as a command line argument, and just do
yes Name | sed "${1}q"
Let sed generate the error message if the parameter is invalid.
The trouble with your loop is that for value in $number takes the string $number and breaks it on whitespace (depends on IFS, actually, but let's not get bogged down by details) and iterates over each value. That is, if $number is the string 1 3 dog 5, then the loop will iterate 4 times with $value taking the values 1, 3, dog, and 5. If $number is 7, then the loop iterates exactly once. You could do for((i=0; i < $number; i++)); do ..., but that does not generate any useful error message if $number is not an integer.
I am trying to make a script that outputs a status bar for my window manager. It outputs the normal stuff like the time, date, weather, etc.
One of the strings it outputs is the number of updates for the system (Arch Linux). As the "API" where I am pulling the update number from has a max number of requests per day I had to add a delay to the updates() function (that outputs the number of updates) so that that maximum number of requests is not exceeded.
Adding this delay makes the problem start.
Somehow the updates_aur variable is not being stored in memory and cannot be accessed until the delay I implemented is removed. (MORE EXPLANATION IN CODE BELOW)
I would like for a delay to be implemented that makes the updates not being checked every iteration but one in 60.
I tried exporting the "updates_aur" and the "updates_arch" to environment variables so that they would be stored in memory but as the script creates a subshell they are not accessible for them to be updated/retrieved.
updates() {
if [ "$internet" = true ]; then
if ! updates_arch=$(checkupdates 2> /dev/null | wc -l ); then
updates_arch=0
fi
if (( $counter % 60 == 0 )); then #this is done to add a delay and not saturate aur requests
if ! updates_aur=$(yay -Qum --devel 2> /dev/null | wc -l); then
updates_aur=0
fi
else
:
fi
updates=$(("$updates_arch" + "$updates_aur"))
if [ "$updates" -gt 0 ]; then
echo " Updates: $updates"
else
echo " Updates: 0"
fi
echo $delim
else
:
fi
}
This is then called in a while loop (the while loop also increments the counter by 1)
Full code: https://github.com/Baitinq/dwm/blob/master/scripts/dwm-status
I expected the variable of aur_updates to be updated and stored whenever the counter % 60 == 0, but the actual result is that the variable can only be accessed when the counter % 60 == 0, as if it wasn't being stored in memory and updated, but created with every while loop iteration in which the counter % 60 == 0.
Since you're running your functions in a subshell, for example (from the status function):
echo $(updates)
Their variables' (updates_aur) values are lost when the subshell exits. There's no reason to echo a function that contains an echo within it. Just call your function directly:
updates
This occurs in several places with other functions. It's also not necessary there.
Scenario:
I have a shell script running on embedded linux. The script starts an application which needs the state of a variable to be on.
Code:
So I do it like this
#!/bin/sh
start_my_app=false
wait_for_something=true
while $wait_for_something; do
wait_for_something=$(cat /some/path/file)
if [ "$wait_for_something" = "false" ]
then
echo Waiting...
elif [ "$wait_for_something" = "true" ]
then
echo The wait has ended
wait_for_something=false
start_my_app=true
else
fi
done
if [ "$start_my_app" = "true" ]
then
/usr/bin/MyApp
fi
#End of the script
/some/path/file has a value false and turns to true in a few seconds by another script in different component. And then as the logic goes wait_for_something in my script becomes true and /usr/bin/MyApp is started.
The problem and hence the question:
But I want to do it in a better way.
I dont want to wait infinitely in a while loop expecting the content value in /some/path/file to be set true after some time.
I want to wait for the content value in /some/path/file to be set true for only 5 seconds. If /some/path/file does not contain true in 5 seconds, I want to get out setting start_my_app to false.
How can I achieve this functionality in a shell script on linux?
PS:
My whole script is run in the background by another script
Use the SECONDS variable as a timer.
SECONDS=0
while (( SECONDS < 5 )) && IFS= read -r value < /some/path/file; do
if [[ $value = true ]]; then
exec /usr/bin/MyApp
fi
done
If you never read true from the file, your script will exit after 5 seconds. Otherwise, the script replaces the current shell with MyApp, effectively exiting the while loop.
I'm looking for a bash script that can parse a time duration.
If three arguments are given, they represent hours, minutes, and seconds. If two arguments are given, they represent minutes and seconds, with the hours zero.
What about the following:
#!/bin/bash
h=0
if [ "$#" -ge 3 ]
then
h=$1
shift
fi
sec=$((3600*$h+60*$1+$2))
echo "The total number of seconds is $sec"
Since the question does not specify what you aim to do with the given time, the program calculates the total number of seconds. Furthermore perhaps it is useful to do a check if at least two arguments are given.
The script uses the shift operation, the shift makes makes $1 := $2; $2 := $3, etc. In other words, the first argument is processed, and then you "pretend" it never existed.
By default you set h to zero, and only if the number of arguments is greater than or equal to 3, it will set h.
This is a more or less general solution for that type of task. Sorry, if it is a monkeycode, but I think it is sufficient:
gettime() {
params=(
years months weeks days hours minutes seconds
)
for i in `seq ${#params}`; do
param_i=$((${#params} - i + 1)) # reversed params index
[ $i -le $# ] && {
eval "local ${params[$param_i]}=\$$(($# - i + 1))"
} || {
eval "local ${params[$param_i]}=0"
}
eval "echo ${params[$param_i]} '==' \$${params[$param_i]}" # debug output
done
}
Here's the sample output:
$ gettime 3 4 5 6 7
seconds == 7
minutes == 6
hours == 5
days == 4
weeks == 3
months == 0
years == 0
Note, that the shell you are using must be not only support POSIX standards, but also arrays.
First Argument: $1
Second Argument: $2
Third Argument: $3
and so on...
Example:
bash-2.05a$ ./parseDuration.sh 13 25 25
13 hours and 25 minutes and 25 seconds
bash-2.05a$ cat ./parseDuration.sh
#!/bin/bash
echo "$1 hours and $2 minutes and $3 seconds"
I'm new to bash scripting and I faced an issue when I tried to improve my script. My script is spliting a text file and each part of this text file is processed in a function ... Everything is working fine but my problem occurs when I'm forking (with &) my function processing ! My args are not like expected (it's a line number and text with whitespaces and backspaces) and I suppose it's because of global variables ... I tried to fork, then sleep 1 second in the parent thread and then continue in order to put args into local variables for my function execution but it doesn't work either ... Can you give me a hint about how to do it ? What I want is to be able to pass args to my function and be allowed to modify it after the fork call in my parent thread ... is it possible ?
Thanks in advance :)
Here is my script :
#!/bin/bash
#Parameters#
FILE='tasks'
LINE_BY_THREAD='500'
#Function definition
function checkPart() {
local NUMBER="$1"
local TXT="$2"
echo "$TXT" | { while IFS= read -r line ; do
IFS=' ' read -ra ADDR <<< "$line"
#If the countdown is set to 0, launch the task ans set it to init value
if [ ${ADDR[0]} == '0' ]; then
#task launching
#to replace by $()l
echo `./${ADDR[1]}.sh ${ADDR[2]} &`
#countdown set to init value
sed -i "$NUMBER c ${ADDR[3]} ${ADDR[1]} ${ADDR[2]} ${ADDR[3]}" $FILE
else
sed -i "$NUMBER c $((ADDR-1)) ${ADDR[1]} ${ADDR[2]} ${ADDR[3]}" $FILE
fi
((NUMBER++))
done }
}
#Init processes number#
LINE_NUMBER=$(wc -l < $FILE)
NB_PROCESSES=$(($LINE_NUMBER / $LINE_BY_THREAD))
if [ $(($LINE_NUMBER % $LINE_BY_THREAD)) -ne '0' ]; then
((NB_PROCESSES++))
fi
echo "Number of thread to be run : $NB_PROCESSES"
#Start the split sequence#
for (( i = 2; i <= $LINE_NUMBER; i += $LINE_BY_THREAD ))
do
PARAM=$(sed "$i,$(($i + $LINE_BY_THREAD - 1))!d" "$FILE")
(checkPart "$i" "$PARAM") &
sleep 1
done
My job is to create a scheduler for tasks described in this following file :
#MinutesBeforeLaunch#TypeOfProcess#Argument#Frequency#
2 agr_m 42 5
5 agr_m_s 26 5
0 agr_m 42 5
3 agr_m_s 26 5
0 agr_m 42 5
5 agr_m_s 26 5
4 agr_m 42 5
5 agr_m_s 26 5
4 agr_m 42 5
4 agr_m_s 26 5
2 agr_m 42 5
4 agr_m_s 26 5
When I'm reading a number > 0 in the first column, I just decrement it and when it's a 0 I have to launch the task and set the first number to frequency, last column ...
My first code is the previous with sed for text replacement but is it possible to do better ?