Unix & Linux Stack Exchange
Q&A for users of Linux, FreeBSD and other Unix-like operating systems
Latest Questions
2
votes
1
answers
133
views
Semicolon in conditional structures after the closing double bracket in a bash/zsh script?
Continuing https://unix.stackexchange.com/questions/48805/semicolon-in-conditional-structures (which handles single brackets), what's the point of having a semicolon after the closing DOUBLE bracket `]]`? In my tests, running ```zsh #!/bin/zsh -- if [[ "a" == "a" ]] then echo "true" else echo "false...
Continuing https://unix.stackexchange.com/questions/48805/semicolon-in-conditional-structures (which handles single brackets), what's the point of having a semicolon after the closing DOUBLE bracket
]]
?
In my tests, running
#!/bin/zsh --
if [[ "a" == "a" ]] then
echo "true"
else
echo "false"
fi
if [[ "a" == "a" ]]; then
echo "true"
else
echo "false"
fi
if [[ "a" == "a" ]]
then
echo "true"
else
echo "false"
fi
if [[ "a" == "a" ]];
then
echo "true"
else
echo "false"
fi
yields
true
true
true
true
, and running
#!/bin/zsh --
if [[ "a" == "b" ]] then
echo "true"
else
echo "false"
fi
if [[ "a" == "b" ]]; then
echo "true"
else
echo "false"
fi
if [[ "a" == "b" ]]
then
echo "true"
else
echo "false"
fi
if [[ "a" == "b" ]];
then
echo "true"
else
echo "false"
fi
yields
false
false
false
false
No error is reported. In zsh, what's the difference between the conditionals with a semicolon ;
after the closing double bracket and the conditionals without a semicolon after the closing double bracket?
The same question goes for bash.
user743115
(1 rep)
Jul 26, 2025, 12:42 AM
• Last activity: Jul 26, 2025, 06:12 PM
0
votes
1
answers
99
views
Should my cat utility support multiple keys simultaneously?
So, i was given a task to implement simple version of cat utility. It should support some of GNU keys, for given text returns the same results as real cat utility and i was given this synopsis: ``` cat [OPTION] [FILE]... ``` What i want to know can my utility be called with multiple keys or just wit...
So, i was given a task to implement simple version of cat utility. It should support some of GNU keys, for given text returns the same results as real cat utility and i was given this synopsis:
cat [OPTION] [FILE]...
What i want to know can my utility be called with multiple keys or just with one?
cat -b file
or
cat -b -s -e file
[POSIX](https://pubs.opengroup.org/onlinepubs/9699919799.2018edition/)(in BaseDefinions, chapter 12) says:
> The notation used for the **SYNOPSIS** sections **imposes requirements on the implementors of the standard utilities** and provides a simple reference for the application developer or system user.
And it the same chapter [POSIX](https://pubs.opengroup.org/onlinepubs/9699919799.2018edition/) says:
> Ellipses ( "..." ) are used to denote that **one or more** occurrences of an operand **are allowed**.
---
So if **OPTION** can be repeated, why there is no ellipsis after it in synopsis? For example, there is an ellipsis [man7.org](https://man7.org/linux/man-pages/man1/cat.1.html) :
-plaintext
cat [OPTION]... [FILE]...
but not [gnu.org](https://www.gnu.org/software/coreutils/manual/html_node/cat-invocation.html)( but this cat allows many options):
-plaintext
cat [option] [file]...
Can someone explain should my program work with many keys at a time and why? And why [gnu.org](https://www.gnu.org/software/coreutils/manual/html_node/cat-invocation.html) doesn't follow this(ellipsis) utility syntax convetion?
Mark
(99 rep)
May 29, 2025, 11:14 AM
• Last activity: May 29, 2025, 05:35 PM
2
votes
2
answers
412
views
Receiving " syntax error near unexpected token `then'" from remote Linux server with if, then, fi
I need help in determining why I get ```none syntax error near unexpected token `then' ``` from the following command: for vm in {20..30} ; do ssh -q -o "StrictHostKeyChecking no" 192.168.210.${vm} "hostname; echo $password | su - root -c \"\ if $(whoami | grep -q root);then echo Good; else echo Bad...
I need help in determining why I get
syntax error near unexpected token `then'
from the following command:
for vm in {20..30} ; do ssh -q -o "StrictHostKeyChecking no" 192.168.210.${vm} "hostname; echo $password | su - root -c \"\ if $(whoami | grep -q root);then echo Good; else echo Bad;fi \"" ; done
vm201scf001
-bash: -c: line 0: syntax error near unexpected token `then'
-bash: -c: line 0: `\ if ;then echo Good; else echo Bad;fi '
This simple command does work though:
for vm in {20..30} ; do ssh -q -o "StrictHostKeyChecking no" 192.168.210.${vm} "hostname; echo $password | su - root -c \"\uptime \"" ; done
vm201scf001
22:11:41 up 422 days, 3:32, 0 users, load average: 0.28, 0.44, 0.52
Does the if
, then
, fi
statement not work in this case? Please advise.
Bjoern
(59 rep)
May 9, 2025, 10:17 PM
• Last activity: May 12, 2025, 12:23 AM
9
votes
1
answers
630
views
Difference between /RE/ and "RE" in awk
In `awk`, the first argument to the `sub()` and `gsub()` functions, the second argument to the `match()` function, and the optional third argument to `split()`, is an extended regular expression. Such an argument may be an arbitrary expression that evaluates to a string interpreted as a regular expr...
In
awk
, the first argument to the sub()
and gsub()
functions, the second argument to the match()
function, and the optional third argument to split()
, is an extended regular expression.
Such an argument may be an arbitrary expression that evaluates to a string interpreted as a regular expression, or it may be a regular expression constant.
In awk
, a regular expression constant is written /RE/
for some regular expression RE
(an "ERE
" token in the awk
grammar).
**Question:** Assuming that RE
remains the same (some non-variable regular expression), are there any practical differences between using /RE/
and using "RE"
(a "STRING
" token in the awk
grammar) in a call to, e.g., sub()
? Alternatively: is there any known awk
implementation that distinguishes between these two ways of representing a regular expression in a call to the above-mentioned functions?
The reason for asking is that I recall having to modify some awk
code that tried to use "RE"
as a regular expression in a call to either sub()
or gsub()
, because, for whatever reason, the awk
implementation at hand did the wrong thing unless I called the function with /RE/
.
Unfortunately, this was some time ago (2+ years), so I don't remember the details, and I am even uncertain what Unix I used at the time (possibly OpenBSD), but I've been meaning to ask the question ever since.
Kusalananda
(354171 rep)
Jan 17, 2023, 02:44 PM
• Last activity: Apr 30, 2025, 09:21 AM
2
votes
2
answers
418
views
Merging values from 2 YAML files in bash
A bash command: $(System.DefaultWorkingDirectory)/yq_linux_amd64 '. *= load("${{ parameters.HELM_CHART_PATH }}/values/DEV/${{ parameters.COMPONENT }}.yaml")' ${{ parameters.HELM_CHART_PATH }}/values/global-values.yaml > $(System.DefaultWorkingDirectory)/deployment-values.yaml Is merging values from...
A bash command:
$(System.DefaultWorkingDirectory)/yq_linux_amd64 '. *= load("${{ parameters.HELM_CHART_PATH }}/values/DEV/${{ parameters.COMPONENT }}.yaml")' ${{ parameters.HELM_CHART_PATH }}/values/global-values.yaml > $(System.DefaultWorkingDirectory)/deployment-values.yaml
Is merging values from 2 YAML files and sending merged output to a single file. I am unable to understand the syntax from the first single quote until the output is redirected. Can anyone help me understand what it means?
Why are both operands after the operator, which is
*=
? .
is the current directory, but what does it mean before *=
?
Also, why only 1st operand is between load ()
and what is its meaning?
Mihir
(47 rep)
Apr 16, 2025, 11:36 PM
• Last activity: Apr 24, 2025, 09:21 PM
5
votes
1
answers
109
views
Why can a list within a group be terminated with a space instead of a semicolon/newline as defined in the manual?
I am using the following version of the bash: ``` GNU bash, version 5.1.16(1)-release (x86_64-pc-linux-gnu) ``` [Man bash](https://www.man7.org/linux/man-pages/man1/bash.1.html#SHELL_GRAMMAR) states the following for the "group" compound commnad: > { list; } > > list is simply executed in the curren...
I am using the following version of the bash:
GNU bash, version 5.1.16(1)-release (x86_64-pc-linux-gnu)
[Man bash](https://www.man7.org/linux/man-pages/man1/bash.1.html#SHELL_GRAMMAR) states the following for the "group" compound commnad:
> { list; }
>
> list is simply executed in the current shell environment.
> list must be terminated with a newline or semicolon. This
> is known as a group command. The return status is the exit
> status of list. Note that unlike the metacharacters ( and
> ), { and } are reserved words and must occur where a
> reserved word is permitted to be recognized. Since they do
> not cause a word break, they must be separated from list by
> whitespace or another shell metacharacter.
Thus, according to it, the following two are valid { echo ok; }
and { { echo ok; }; }
. In second case I have a group within a group.
However, what confuses me is the following example: { { echo ok; } }
. It also works, but how is that possible? According to the manual, the list within {
and }
must end with a semicolon (or newline). In my example inner group (which is the list for the outer group) does not end with a semicolon (or newline), but with a space (we should have ;
after the first }
).
Why does this work?
Yakog
(517 rep)
Mar 14, 2025, 06:28 PM
• Last activity: Mar 15, 2025, 11:37 AM
2
votes
1
answers
728
views
How does the nftables set-syntax replacement for meters work exactly?
nftables nowadays [recommends](https://wiki.nftables.org/wiki-nftables/index.php/Meters) to use sets instead of meters when e.g. creating dynamic per-IP blacklists (example adapted from [man pages](https://manpages.debian.org/testing/nftables/nft.8.en.html) v0.98: ``` set blackhole { type ipv4_addr...
nftables nowadays [recommends](https://wiki.nftables.org/wiki-nftables/index.php/Meters) to use sets instead of meters when e.g. creating dynamic per-IP blacklists (example adapted from [man pages](https://manpages.debian.org/testing/nftables/nft.8.en.html) v0.98:
set blackhole {
type ipv4_addr
flags dynamic
timeout 30m
}
set flood {
type ipv4_addr
flags dynamic
timeout 1m
}
ip saddr @blacklist drop
ct state new \
add @flood { ip saddr limit rate over 10/minute } \
add @blacklist { ip saddr } \
drop
1. How is the execution flow of the add
-statements here? The second add
is only executed when the per-ip limit specified in the first add
is hit, but why? Does it have something to do with whether the first add
actually does anything (i.e. there is no entry in the table yet)? Or does it do some magic by looking at the set and the number of connections created so far?
2. Is the drop
always executed? Or just after the second add
is evaluated? Why?
3. How does the lookup table help to keep track of the limit? When I view the actual contents of the set, I don't see any counts of e.g. new connections in the last minute. Does it just store the timestamp and delegate the actual counting to the kernel?
4. Why do we need to specify the flood limit interval twice (as the set timeout
and in the limit
statement)? Are there use-cases where it makes sense to use two different values?
5. The [Red Hat 7 docs](https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/7/html/security_guide/sec-using_nftables_to_limit_the_amount_of_connections) give this example for a per-IP connection limiter:
nft add rule ip filter input ip protocol tcp ct state new, untracked limit rate over 10/minute add @denylist { ip saddr }
This seems incorrect to me as the rate is put _before_ the add
, meaning it will just add the IP to the table as soon as it hits 10 new connections/minute from _any_ IP?
Pointers to docs on the actual semantics of the language are appreciated.
reijerh
(31 rep)
Mar 28, 2023, 10:50 PM
• Last activity: Jan 23, 2025, 12:22 AM
0
votes
4
answers
96
views
Details with bash's syntax checking and breaking over several lines
There are two cases in which I do not understand why bash behaves as it behaves regarding syntax checking and asking for a newline. # Case 1 bash can execute the line `( (ls) | cat)`, but depending on when you hit return while entering, it might work or not. This works: ``` ( (ls ) |⏎ cat ``` This f...
There are two cases in which I do not understand why bash behaves as it behaves regarding syntax checking and asking for a newline.
# Case 1
bash can execute the line
( (ls) | cat)
, but depending on when you hit return while entering, it might work or not.
This works:
( (ls ) |⏎
cat
This fails:
( (ls) ⏎
| cat)
with error
>-bash: syntax error near unexpected token `|'
Is there a logic why the second case is not working? Or it is just how bash works internally?
# Case 2
Another thing I do not understand is, that, when you enter (ls) "⏎
bash asks for another line. Is there any way to finish this command without getting a syntax error? And if not, why does bash not directly print out an error message for a syntax error?
Bastian
(25 rep)
Dec 16, 2024, 04:10 PM
• Last activity: Dec 17, 2024, 09:26 AM
2
votes
1
answers
65
views
Get PID of command in one line bash script
When trying to get the PID of a shell command, it is possible using a script file: ```bash #!/bin/bash ls -lha & echo "$!" ``` However, it is not possible using only the terminal. `/bin/bash -c 'ls -lha & ; echo "$!"'` This returns the error: > /bin/bash: -c: line 1: syntax error near unexpected tok...
When trying to get the PID of a shell command, it is possible using a script file:
#!/bin/bash
ls -lha &
echo "$!"
However, it is not possible using only the terminal.
/bin/bash -c 'ls -lha & ; echo "$!"'
This returns the error:
> /bin/bash: -c: line 1: syntax error near unexpected token `;'
The manual states the following:
> A *list* is a sequence of one or more pipelines
separated by one of the operators ;
, &
, &&
, or ||
,
and optionally terminated by one of ;
, &
, or ``.
Of these list operators, &&
and ||
have equal precedence,
followed by ;
and &
, which have equal precedence.
>
>A sequence of one or more newlines may appear in a *list*
instead of a semicolon to delimit commands.
>
> If a command is terminated by the control operator &
,
the shell executes the command in the background in a subshell.
The shell does not wait for the command to finish,
and the return status is 0.
Commands separated by a ;
are executed sequentially;
the shell waits for each command to terminate in turn.
The return status is the exit status of the last command executed.
So I also tried using newline, but was not able to use it:
/bin/bash -c 'ls -lha & \n echo "$!"'
### How can I call a shell command to run on background and get the PID?
P.S.: I will not use ls
command and it is a more complex script.
This is just a minimal example to reproduce the problem.
danieltakeshi
(131 rep)
Dec 5, 2024, 07:15 PM
• Last activity: Dec 5, 2024, 10:58 PM
-5
votes
1
answers
60
views
After wrote prompt $ sort
After I wrote prompt **$ sort** display doesn't shown anything what the next step?
After I wrote prompt **$ sort**
display doesn't shown anything what the next step?
Wahyu Irawan
(1 rep)
Oct 1, 2024, 04:24 AM
• Last activity: Oct 1, 2024, 04:50 AM
4
votes
3
answers
648
views
Correctly defining a Cron schedule for process to be run every hour
There is a record: 45 * * * 1 script.sh and 45 0-23 * * 1 script.sh The desired effect is to run the script 45 minutes after every hour on Mondays. Are they identical? If not, what is the difference?
There is a record:
45 * * * 1 script.sh
and
45 0-23 * * 1 script.sh
The desired effect is to run the script 45 minutes after every hour on Mondays.
Are they identical? If not, what is the difference?
Zaza
(604 rep)
Jul 18, 2017, 10:43 AM
• Last activity: Aug 11, 2024, 09:54 AM
0
votes
1
answers
1303
views
bash 5.2.x + ternary operator: How can I use this combo when checking if my string variable is empty or not?
I have tried #!/bin/bash distro="" myvar1=[[ -n "$distro" ]] && echo $distro || echo "debian" myvar2=$((-n $distro ? $distro : "debian")) these are the results of the script ./build.sh: line 5: -n: command not found debian ./build.sh: line 6: -n ? : debian: expression expected (error token is ": deb...
I have tried
#!/bin/bash
distro=""
myvar1=[[ -n "$distro" ]] && echo $distro || echo "debian"
myvar2=$((-n $distro ? $distro : "debian"))
these are the results of the script
./build.sh: line 5: -n: command not found
debian
./build.sh: line 6: -n ? : debian: expression expected (error token is ": debian")
mrjayviper
(2253 rep)
Aug 6, 2024, 05:50 AM
• Last activity: Aug 6, 2024, 07:40 AM
0
votes
5
answers
152
views
What is the difference between using code $variable and ${variable}2?
What is the difference between using code $variable and ${variable}2 ? Example: file ='GLOBAL_AR_COLLECTOR_COMMENTS20240614ALYSSAB.TXT' prefix ='GLOBAL_AR_COLLECTOR_COMMENTS' In my shell script code written like below, if echo $file |grep -q $prefix*.TXT if echo $file | grep -q ${prefix}2*.TXT i wou...
What is the difference between using code $variable and ${variable}2 ?
Example:
file ='GLOBAL_AR_COLLECTOR_COMMENTS20240614ALYSSAB.TXT'
prefix ='GLOBAL_AR_COLLECTOR_COMMENTS'
In my shell script code written like below,
if echo $file |grep -q $prefix*.TXT
if echo $file | grep -q ${prefix}2*.TXT
i would like to know, what is the difference between both the if conditions?.
What is the use of {prefix} ? , and why we are using 2 with ${prefix}2?
Celestica - Prabhahar Palanive
(19 rep)
Jul 24, 2024, 05:57 AM
• Last activity: Jul 25, 2024, 04:28 PM
3
votes
1
answers
461
views
What is the precedence of operators '=', '||'
In this command, if curl succeeds, then `res` will be set to the output of curl. It seems `=` has higher precedence than `||`. res=$(curl -s "http://example.com")||true But `||` should have higher precedence than `=` according to this link: https://tldp.org/LDP/abs/html/opprecedence.html What is goi...
In this command, if curl succeeds, then
res
will be set to the output of curl. It seems =
has higher precedence than ||
.
res=$(curl -s "http://example.com ")||true
But ||
should have higher precedence than =
according to this link: https://tldp.org/LDP/abs/html/opprecedence.html
What is going on?
lamplet
(35 rep)
Jul 24, 2024, 04:01 AM
• Last activity: Jul 24, 2024, 02:28 PM
25
votes
2
answers
35607
views
What does command eval "$(/opt/homebrew/bin/brew shellenv)" actually do?
Homebrew requires us to add `eval $(/opt/homebrew/bin/brew shellenv)` to `~/.zprofile`. What does this actually evaluate to and what does this accomplish? I am a bit new to shell scripting. I know `$var` is used to refer to a variable named var but that's about it. What is the meaning of putting a p...
Homebrew requires us to add
eval $(/opt/homebrew/bin/brew shellenv)
to ~/.zprofile
. What does this actually evaluate to and what does this accomplish?
I am a bit new to shell scripting. I know $var
is used to refer to a variable named var but that's about it. What is the meaning of putting a path inside of $()
? Also is shellenv
an argument here and what does it signify?
Osbridge
(353 rep)
Feb 17, 2023, 12:17 AM
• Last activity: Jul 11, 2024, 08:35 AM
3
votes
1
answers
235
views
Convention of parameter naming - undocumented options
GNU has long pushed for a combination of short options (`-h`) and long options (`--help`), which goes a long way to clearing up the syntactical mess of commands like `tar` and `dd`, with their legacy syntax going back to the stone age. But I recently [learned][1] that GNU's `parted` has a _third_ ki...
GNU has long pushed for a combination of short options (
-h
) and long options (--help
), which goes a long way to clearing up the syntactical mess of commands like tar
and dd
, with their legacy syntax going back to the stone age.
But I recently learned that GNU's parted
has a _third_ kind of option, where an 'undocumented feature' can be accessed with ---pretend-input-tty
. It looks like it was introduced in this commit in 2007.
It's the first time I've seen that, and I'm intrigued. Is this some kind of wider convention, or just a one-off?
Popup
(704 rep)
Jun 21, 2024, 06:53 AM
• Last activity: Jun 21, 2024, 09:18 AM
-1
votes
1
answers
113
views
How to specify several alternative conditions (OR operator) for single case statement? (Or Alternatively, where is shell case syntax description?)
I want something like this: ```shell time="1m" case "$time" in *h*) *m*) *s*) echo "handling several cases for h, m, s tokens" ;; *) echo "handling other cases" ;; esac ``` How to achieve this for POSIX shell?
I want something like this:
time="1m"
case "$time" in
*h*)
*m*)
*s*)
echo "handling several cases for h, m, s tokens" ;;
*)
echo "handling other cases" ;;
esac
How to achieve this for POSIX shell?
Anton Samokat
(289 rep)
May 10, 2024, 02:08 PM
• Last activity: Jun 9, 2024, 06:35 AM
0
votes
1
answers
213
views
ShellCheck does not detect error? How to fix my snippet?
I likely have syntax errors in the following (POSIX) shell snippet: ```sh #!/bin/sh if tput setaf >/dev/null 2>&1; then tput_init_linux else tput_init_none; elif tput AF >/dev/null 2>&1; then tput_init_bsd else tput_init_none; else tput_init_none; fi ``` ShellCheck 0.10.0 does say nothing about it,...
I likely have syntax errors in the following (POSIX) shell snippet:
#!/bin/sh
if tput setaf >/dev/null 2>&1; then tput_init_linux else tput_init_none;
elif tput AF >/dev/null 2>&1; then tput_init_bsd else tput_init_none;
else tput_init_none; fi
ShellCheck 0.10.0 does say nothing about it, I found it basically by accident.
I tested as follows:
1)
if tput setaf >/dev/null 2>&1; then tput_init_linux else tput_init_none; fi
this went ok: tput_init_linux: command not found
2) Reverting the logic with !
:
if ! tput setaf >/dev/null 2>&1; then tput_init_linux else tput_init_none; fi
**says nothing**, but if I add one semicolon:
3)
if ! tput setaf >/dev/null 2>&1; then tput_init_linux; else tput_init_none; fi
it appears to work as expected: tput_init_none: command not found
***
But I seem to be unable to chain these multiple if
-statements afterward.
***
So as you can see, I reached a state, where one statement works, but chaining it seems _problematic_. Can anyone help?
Vlastimil Burián
(30505 rep)
May 23, 2024, 07:08 AM
• Last activity: May 24, 2024, 10:38 AM
841
votes
5
answers
389036
views
What does "--" (double dash / double hyphen) mean?
I have seen `--` used in the `compgen` command. For example: compgen -W "foo bar baz" -- b What is the meaning of the `--` in there?
I have seen
--
used in the compgen
command.
For example:
compgen -W "foo bar baz" -- b
What is the meaning of the --
in there?
dogbane
(30645 rep)
Apr 15, 2011, 12:39 PM
• Last activity: May 17, 2024, 05:47 PM
-1
votes
1
answers
92
views
awk inside function causing errors
I'm trying to add the following to my .bashrc: cpu_info() { top -b -n1 | grep Cpu(s) | awk '{print $2 + $4}' } but bash is telling me: bash: .bashrc: line 131: syntax error near unexpected token `(' bash: .bashrc: line 131: ` top -b -n1 | grep Cpu(s) | awk '{print $2 + $4}'' the command works fine i...
I'm trying to add the following to my .bashrc:
cpu_info() {
top -b -n1 | grep Cpu(s) | awk '{print $2 + $4}'
}
but bash is telling me:
bash: .bashrc: line 131: syntax error near unexpected token `('
bash: .bashrc: line 131: ` top -b -n1 | grep Cpu(s) | awk '{print $2 + $4}''
the command works fine in the terminal, not sure why its breaking in my bash script
any ideas?
Mathew
(243 rep)
May 10, 2024, 04:47 PM
• Last activity: May 11, 2024, 05:00 AM
Showing page 1 of 20 total questions