Unix & Linux Stack Exchange
Q&A for users of Linux, FreeBSD and other Unix-like operating systems
Latest Questions
66
votes
5
answers
77086
views
What is "declare" in Bash?
After reading ilkkachu's answer to [this question][1] I learned on the existence of the `declare` (with argument `-n`) shell built in. `help declare` brings: > Set variable values and attributes. > > Declare variables and give them attributes. If no NAMEs are given, > display the attributes and valu...
After reading ilkkachu's answer to this question I learned on the existence of the
declare
(with argument -n
) shell built in.
help declare
brings:
> Set variable values and attributes.
>
> Declare variables and give them attributes. If no NAMEs are given,
> display the attributes and values of all variables.
> -n ... make NAME a reference to the variable named by its value
I ask for a general explanation with an example regarding declare
because I don't understand the man
. I know what is a variable and expanding it but I still miss the man
on declare
(variable attribute?).
Maybe you'd like to explain this based on the code by ilkkachu in the answer:
#!/bin/bash
function read_and_verify {
read -p "Please enter value for '$1': " tmp1
read -p "Please repeat the value to verify: " tmp2
if [ "$tmp1" != "$tmp2" ]; then
echo "Values unmatched. Please try again."; return 2
else
declare -n ref="$1"
ref=$tmp1
fi
}
user149572
Apr 3, 2019, 06:49 AM
• Last activity: Jun 11, 2025, 10:39 AM
2
votes
1
answers
2229
views
Zsh: timeout for vared builtin
I've got a while loop that uses [`vared`](http://zsh.sourceforge.net/Doc/Release/Zsh-Line-Editor.html#index-vared) to prompt for user input. I am looking for a way to have it timeout, execute a default variable and loop back to the prompt if there is not user input after a certain amount of time. I...
I've got a while loop that uses [
vared
](http://zsh.sourceforge.net/Doc/Release/Zsh-Line-Editor.html#index-vared) to prompt for user input. I am looking for a way to have it timeout, execute a default variable and loop back to the prompt if there is not user input after a certain amount of time. I am aware of the read command and its timeout argument, but is this somehow possible with vared
?
Also, is there a way to set a default for vared
that doesn't print to the prompt?
local command
while :
do
echo "Enter a command or type 'quit' to exit:"
vared -p "[*]: " command
if [ "$command" = "quit" ]; then
break
else
run command
fi
clear
done
Кафка
(161 rep)
Feb 4, 2020, 12:42 PM
• Last activity: Sep 30, 2024, 07:05 AM
1
votes
3
answers
310
views
How to tail continuously a log file that is being deleted and recreated?
I need to extract information from a log file that is deleted and recreated every time a program runs. After detecting that the file exists (again), I would like to `tail` it for a certain regexp. The regexp will be matched a few times, but the result is always the same and I want to print it just o...
I need to extract information from a log file that is deleted and recreated every time a program runs. After detecting that the file exists (again), I would like to
tail
it for a certain regexp.
The regexp will be matched a few times, but the result is always the same and I want to print it just once and after that go back to monitoring when the file is re-created.
I looked at ways of detecting file creation. One way would be via inotifywait
, but that requires installing a separate package.
Perhaps a simpler way is to take advantage that tail prints to stderr
when a file that is being tailed is deleted and created:
tail: '/path/to/debug.log' has become inaccessible: No such file or directory
tail: '/path/to/debug.log' has appeared; following new file
So I applied this solution which is working:
debug_file="/path/to/debug.log"
while true; do
# Monitor the log file until the 'new file' message appears
( tail -F $debug_file 2>&1 & ) | grep -q "has appeared; following new file"
# After the new file message appears, switch to monitoring for the regexp
tail -F "$debug_file" | while read -r line; do
id=$(echo "$line" | sed -n 's/.* etc \([0-9]\+\),.*/\1/p')
if [ -n "$id" ]; then
echo "ID: $id"
break # Exit the inner loop after the first match
fi
done
done
But I don't like that this solution starts 2 different tail
processes. Is there a way to achieve the same result, but using just 1 tail
process?
And then switch 'modes', start by looking for file creation, then look for the regexp and once that is found go back to 'standby' mode waiting for the log file to be deleted and created again.
Is inotifywait a more elegant solution? Ideally I would like a solution I could port easily to Windows CMD.
user2066480
(173 rep)
Mar 19, 2024, 05:27 PM
• Last activity: Mar 20, 2024, 12:16 PM
0
votes
1
answers
143
views
Is a newline equivalent to && in a bash script?
I'm very simply wondering if, in a bash script, a new line is functionally 100% equivalent to `&&`? e.g.: ``` #!/bin/bash 7z x "${file}" mv "${file}" "${new_file}" ``` vs ``` #!/bin/bash 7z x "${file}" && mv "${file}" "${new_file}" ``` GNU bash, version 5.1.16(1)-release (x86_64-pc-linux-gnu)
I'm very simply wondering if, in a bash script,
a new line is functionally 100% equivalent to
&&
?
e.g.:
#!/bin/bash
7z x "${file}"
mv "${file}" "${new_file}"
vs
#!/bin/bash
7z x "${file}" && mv "${file}" "${new_file}"
GNU bash, version 5.1.16(1)-release (x86_64-pc-linux-gnu)
s.k
(511 rep)
Mar 9, 2024, 07:10 PM
• Last activity: Mar 9, 2024, 10:20 PM
5
votes
5
answers
2269
views
Multiple Command List After Shell Conditionals, &&, ||. Shell Script, Dash
I'm trying to do multiple commands after a condition, so for example... [ $VAR ] || echo "Error msg" ; echo "exit" and the Inverse [ -z $VAR ] && echo "Error msg" ; echo "exit" I know that won't work as intended, I actually knew how previously and forgot how to do this. I'm fully aware of the many a...
I'm trying to do multiple commands after a condition, so for example...
[ $VAR ] || echo "Error msg" ; echo "exit"
and the Inverse
[ -z $VAR ] && echo "Error msg" ; echo "exit"
I know that won't work as intended, I actually knew how previously and forgot how to do this. I'm fully aware of the many alternatives, such as using
if
's or bracketing via ()
and {}
. Using ()
will create a sub process which wouldn't exit a running script. Using {}
will work, but I know a more readable alternative exists.
I have done this with a :
, and it was perfect!!! I just can't remember now for the life of me, and I lost that previously written script.
If anyone knows how to write this with the :
's, I would really appreciate any help!
J. M. Becker
(5049 rep)
Dec 27, 2011, 04:10 AM
• Last activity: Nov 19, 2023, 12:07 PM
2
votes
4
answers
143
views
How to execute a command after the previous non-terminating command prints a certain string?
I want to execute `commandA` which prints the following: ```none line1 line2 line3 started successfully line4 ... ... ``` And when the line `started successfully` is printed I want to start another command (and possibly multiplex their outputs so that both are printed on the terminal). How could I a...
I want to execute
commandA
which prints the following:
line1
line2
line3
started successfully
line4
...
...
And when the line started successfully
is printed I want to start another command (and possibly multiplex their outputs so that both are printed on the terminal).
How could I achieve this in bash?
Marinos An
(889 rep)
Aug 1, 2023, 01:00 PM
• Last activity: Oct 5, 2023, 05:01 PM
4
votes
2
answers
26078
views
How to use user input as a while loop condition
I can do this in bash: while read -n1 -r -p "choose [y]es|[n]o" do if [[ $REPLY == q ]]; then break; else #whatever fi done which works but seems a bit redundant, can i do something like this instead? while [[ `read -n1 -r -p "choose [y]es|[n]o"` != q ]] do #whatever done
I can do this in bash:
while read -n1 -r -p "choose [y]es|[n]o"
do
if [[ $REPLY == q ]];
then
break;
else
#whatever
fi
done
which works but seems a bit redundant, can i do something like this instead?
while [[
read -n1 -r -p "choose [y]es|[n]o"
!= q ]]
do
#whatever
done
razzak
(297 rep)
Sep 7, 2015, 10:50 PM
• Last activity: Sep 21, 2022, 02:14 PM
5
votes
3
answers
962
views
Tool to detect errors in application's execution logic
I want to detect errors in application's execution logic. E.g.: - forgot to call `free()` on address returned by `malloc()` - did not close file handle returned by `open()` - invalid flags passed to `open()` - invalid file handle passed to `poll()` - `write()` called on fd that wasn't opened for wri...
I want to detect errors in application's execution logic. E.g.:
- forgot to call
free()
on address returned by malloc()
- did not close file handle returned by open()
- invalid flags passed to open()
- invalid file handle passed to poll()
- write()
called on fd that wasn't opened for writing
- pass invalid flags to open()
e.g. open("/etc/fstab", 4)
- calling close()
on an invalid fd
- ...
I think there are hundreds more.
Maybe the tool can be run similar to ftrace
or strace
, but a kernel log containing the faulty calls would be sufficient too.
zomega
(1012 rep)
Jul 6, 2022, 09:30 AM
• Last activity: Jul 7, 2022, 04:35 PM
0
votes
0
answers
28
views
How do I get this code to evaluate all arms of if-else? Why does Bash seem to interpret the characters that I input as integers?
The last `elif` arm does not get executed: ``` #!/usr/bin/bash searches=("feet" "axilas" "lactant") length=${#searches[@]} searchFunction() { echo "Enter the respective number to go for the specific search. Otherwise type 'a' to loop through all of them." read i if [[ $i -lt $length && $i -gt -1 ]]...
The last
elif
arm does not get executed:
#!/usr/bin/bash
searches=("feet"
"axilas"
"lactant")
length=${#searches[@]}
searchFunction() {
echo "Enter the respective number to go for the specific search.
Otherwise type 'a' to loop through all of them."
read i
if [[ $i -lt $length && $i -gt -1 ]] ; then
echo "within range"
exit 0
elif [[ $i -ge $length || $i -lt 0 ]] ; then
echo "Your choice is out of range. Exiting."
exit 0
elif [[ $i == 'a' ]]; then
echo "todo" #this does not get executed, why so?
fi }
echo "The following are the search terms:"
for index in "${!searches[@]}"
do
echo ${index} ${searches[index]}
done
searchFunction
When I switch the order of evaluation and add else
, like so:
searchFunction() {
echo "Enter the respective number to go for the specific search.
Otherwise type 'a' to loop through all of them."
read i
if [[ $i == 'a' ]]; then
echo "todo"
elif [[ $i -lt $length && $i -gt -1 ]] ; then
echo "within range"
exit 0
elif [[ $i -ge $length || $i -lt 0 ]] ; then
echo "Your choice is out of range. Exiting."
exit 0
else
exit 0
fi }
then the code works almost as intended ("todo" gets echoed but the issue is that
when other non-numeric characters are given it prints "within range"). Why does Bash seem to interpret the characters that I input as integers?
How might I improve on this?
John Smith
(23 rep)
Feb 16, 2022, 09:52 AM
• Last activity: Feb 16, 2022, 10:17 AM
578
votes
10
answers
1070880
views
How to conditionally do something if a command succeeded or failed
How can I do something like this in bash? if "`command` returns any error"; then echo "Returned an error" else echo "Proceed..." fi
How can I do something like this in bash?
if "
command
returns any error";
then
echo "Returned an error"
else
echo "Proceed..."
fi
Shinmaru
Oct 16, 2011, 09:25 PM
• Last activity: Jan 10, 2022, 04:14 PM
92
votes
6
answers
334465
views
How to loop over the lines of a file?
Say I have this file: hello world hello world This program #!/bin/bash for i in $(cat $1); do echo "tester: $i" done outputs tester: hello tester: world tester: hello tester: world I'd like to have the `for` iterate over each line individually ignoring whitespaces though, i.e. the last two lines sho...
Say I have this file:
hello
world
hello world
This program
#!/bin/bash
for i in $(cat $1); do
echo "tester: $i"
done
outputs
tester: hello
tester: world
tester: hello
tester: world
I'd like to have the
for
iterate over each line individually ignoring whitespaces though, i.e. the last two lines should be replaced by
tester: hello world
Using quotes for i in "$(cat $1)";
results in i
being assigned the whole file at once. What should I change?
Tobias Kienzler
(9574 rep)
Feb 7, 2011, 10:28 AM
• Last activity: Nov 21, 2021, 09:34 PM
0
votes
0
answers
15
views
my if statement is returning command not found
in my script an if statement returns: line 3: []: command not found the statement: ``` if ["$(pidof -x $(basename $0) -o %PPID)"]; then echo process already running; exit; fi ``` what I tried: ``` if [["$(pidof -x $(basename $0) -o %PPID)"]]; then echo process already running; exit; fi ``` ``` if [[...
in my script
an if statement
returns:
line 3: []: command not found
the statement:
if ["$(pidof -x $(basename $0) -o %PPID)"]; then
echo process already running; exit;
fi
what I tried:
if [["$(pidof -x $(basename $0) -o %PPID)"]]; then
echo process already running; exit;
fi
if [["$(pidof -x basename $0 -o %PPID)"]]; then
echo process already running; exit;
fi
if ["$(pidof -x basename $0 -o %PPID)"]; then
echo process already running; exit;
fi
if [[$(pidof -x basename $0 -o %PPID)]]; then
echo process already running; exit;
fi
none seems to work.I get similar error.
line 3: [[]]: command not found
I got the code from here:
https://linuxpip.org/rclone-examples/
https://forum.rclone.org/t/continuous-syncing/12377/2
I did research here:
https://wiki.bash-hackers.org/syntax/ccmd/conditional_expression
and looked at the man bash’s Compound Commands section
but they don’t seem to help.
please help
Thank you!
andy
(1 rep)
Oct 18, 2021, 04:15 AM
441
votes
3
answers
228811
views
What are the shell's control and redirection operators?
I often see tutorials online that connect various commands with different symbols. For example: command1 | command2 command1 & command2 command1 || command2 command1 && command2 Others seem to be connecting commands to files: command1 > file1 command1 >> file1 What are these things? What are they ca...
I often see tutorials online that connect various commands with different symbols. For example:
command1 | command2
command1 & command2
command1 || command2
command1 && command2
Others seem to be connecting commands to files:
command1 > file1
command1 >> file1
What are these things? What are they called? What do they do? Are there more of them?
----
[Meta thread about this question.](https://unix.meta.stackexchange.com/q/3177/22222) .
terdon
(251585 rep)
Oct 6, 2014, 02:18 AM
• Last activity: Sep 30, 2021, 01:13 PM
6
votes
1
answers
7328
views
if ! <command> (...) vs. <command> ; if [ $? -eq 0 ] (...)
I am working on a shell script and decided to check my work via [shellcheck.net][1]. I am able to get functionally the same behavior of the following two lines in my script: findmnt /dev/sda1 >/dev/null ; if [ $? -eq 0 ]; then echo 1; else echo 0; fi vs. if ! findmnt /dev/sda1 >/dev/null; then echo...
I am working on a shell script and decided to check my work via shellcheck.net . I am able to get functionally the same behavior of the following two lines in my script:
findmnt /dev/sda1 >/dev/null ; if [ $? -eq 0 ]; then echo 1; else echo 0; fi
vs.
if ! findmnt /dev/sda1 >/dev/null; then echo 0; else echo 1; fi
However shellcheck throws :
> SC2181: Check exit code directly with e.g. 'if mycmd;', not indirectly
> with $?.
It is not immediately clear to me which to use. I do see: https://github.com/koalaman/shellcheck/issues/1167 which seems to have amended this for several possible values. I want to be sure that I am writing something that uses best practices and will run without issue and report accurately.
Kahn
(1827 rep)
Sep 28, 2021, 06:45 PM
• Last activity: Sep 28, 2021, 07:47 PM
109
votes
9
answers
151164
views
Press space to continue
How do I stop a bash script until a user has pressed Space ? I would like to have the question in my script > Press space to continue or CTRL + C to exit and then the script should stop and wait until Space is pressed.
How do I stop a bash script until a user has pressed Space?
I would like to have the question in my script
> Press space to continue or CTRL+C to exit
and then the script should stop and wait until Space is pressed.
rubo77
(30435 rep)
Jun 4, 2014, 10:42 AM
• Last activity: Sep 3, 2021, 07:12 AM
6
votes
2
answers
3204
views
[ vs [[ : which one to use in bash scripts?
The zsh man page, in its section on `test` (aka `[`), explicitly advises against using it at all, and urges readers to use `[[` whenever possible. The [relevant section][1] states: > The command attempts to implement POSIX and its extensions where these are specified. Unfortunately there are intrins...
The zsh man page, in its section on
test
(aka
), explicitly advises against using it at all, and urges readers to use [[
whenever possible.
The [relevant section states:
> The command attempts to implement POSIX and its extensions where these are specified. Unfortunately there are intrinsic ambiguities in the syntax; in particular there is no distinction between test operators and strings that resemble them. The standard attempts to resolve these for small numbers of arguments (up to four); for five or more arguments compatibility cannot be relied on. Users are urged wherever possible to use the '[[
' test syntax which does not have these ambiguities.
I think I've come across similar advice for bash, but as I scan over the bash man page I can't find any "official" recommendation there on which form ([
or [[
) to use. (Maybe I missed it?)
>Is there any reason, *other than backward compatibility with "older shells"*, for using [
in a bash script? Or to put it differently, does bash keep [
along with [[
for reasons *other* than backward compatibility?
kjo
(16299 rep)
Mar 7, 2013, 10:51 AM
• Last activity: Sep 1, 2021, 04:01 PM
12
votes
3
answers
2241
views
Send task to background in an "if"
Why is this? if true; then sleep 3 &; fi bash: syntax error near unexpected token `;' I want to run sleep 3 in the background so that the command ["sleep 3" is just an example] would run in "paralell" style, so it finishes faster. But I'm getting this: bash: syntax error near unexpected token `;' er...
Why is this?
if true; then sleep 3 &; fi
bash: syntax error near unexpected token `;'
I want to run
sleep 3
in the background so that the command ["sleep 3" is just an example] would run in "paralell" style, so it finishes faster. But I'm getting this:
bash: syntax error near unexpected token `;'
error message. Why? Why can't I send a task to the background?
LanceBaynes
(41465 rep)
Dec 10, 2011, 11:28 AM
• Last activity: May 31, 2021, 05:12 PM
2
votes
1
answers
410
views
Executing a remote script from a code repository causes endless loop
I often execute raw versions of remote Bash scripts in GitHub with this pattern: wget -O - https://raw.githubusercontent.com/ / / / / | bash Generally I can do it without problems but since I have added the following code to a certain script I get an endless loop of `echo` (it often occurs even if I...
I often execute raw versions of remote Bash scripts in GitHub with this pattern:
wget -O - https://raw.githubusercontent.com///// | bash
Generally I can do it without problems but since I have added the following code to a certain script I get an endless loop of
Do you find any problem either in the single lined execution command and/or in the
echo
(it often occurs even if I just copy-paste it from GitHub to the terminal and execute directly):
while true; do
read -p "Example question: Do you wish to edit the PHP file now?" yn
case $yn in
[Yy]* ) nano PROJECT/PHP_FILE; break;;
[Nn]* ) break;;
* ) echo "Please answer yes or no.";;
esac
done
I can at least partly solve the problem with something like:
cd ACTION_DIRECTORY
wget https://raw.githubusercontent.com///// &&
source FILENAME &&
rm FILENAME
Which indicates that the | bash
piping at least worsens the problem because the problem **always** happens with it.
Why would echo "Please answer yes or no."
happen "endlessly"? (which I stop it with CTRLC+C)Do you find any problem either in the single lined execution command and/or in the
while true; do case esac done
?
variable_expander
(45 rep)
Mar 20, 2021, 05:32 AM
• Last activity: Mar 20, 2021, 12:57 PM
0
votes
1
answers
30
views
Pausing script execution until user quits out of `less`
**Goal**: `less` the contents (from a variable) and then ask the user whether the contents should be saved to a file (i.e., `.recovered_object`) *only after* the user quits out of `less`. The excerpt from my script is reproduced below: ```zsh ... # Show each blob until one is chosen counter=1 while...
**Goal**:
less
the contents (from a variable) and then ask the user whether the contents should be saved to a file (i.e., .recovered_object
) *only after* the user quits out of less
.
The excerpt from my script is reproduced below:
...
# Show each blob until one is chosen
counter=1
while IFS='' read sha; do
printf "Showing blob %d of %d" "$counter" "$BLOB_COUNT"
contents=$(git show ${sha})
${PAGER:-less} ${contents}
if read -q '?Save and quit (y/n) ?'; then
echo "$contents" > .recovered_object
exit 0
else
((counter++))
fi
done <<< ${DANGLING_BLOBS_SHA}
exit 0
As it stands now, any keypress (other than y
) skips to the next file...but this precludes the user from scrolling up (k
) or down (j
) or using less
's other keymappings!
How do I prevent the if
block from immediately running?
---
PS: I'm pretty new to shell scripting in general, so any pointers are welcome.
PSS: I am using zsh
, but am not opposed to switching to bash
if that's more conducive to achieving the desired UX.
Per48edjes
(13 rep)
Mar 1, 2021, 03:01 AM
• Last activity: Mar 1, 2021, 04:02 AM
0
votes
2
answers
331
views
How to modify and write to file before printing to STDERR
I am working on an automated pull request check via GitHub actions and I want to preserve some data from a command's `stderr` output between jobs. For this, I need to write the `stderr` to an *artifact* file, but before that I need to also remove some control chars from it via `sed`, otherwise I end...
I am working on an automated pull request check via GitHub actions and I want to preserve some data from a command's
stderr
output between jobs.
For this, I need to write the stderr
to an *artifact* file, but before that I need to also remove some control chars from it via sed
, otherwise I end up with something like:
\x1b[31mFound 344 errors!\x1b[39;49m
I then want the main command to return the same exit code in order to fail the check and prevent merging of the pull request.
I can probably take care of a subset of what needs doing, but am unable to take care of all 3 together together (sed > file write > stderr). If it makes it easier, I am okay with writing both stdout
and stderr
to the file as well.
Open to suggestions to do this differently.
Abhishek Jain
(119 rep)
Nov 28, 2020, 05:52 PM
• Last activity: Dec 3, 2020, 10:46 AM
Showing page 1 of 20 total questions