Why doesn't using multiple commands with a || or && conditional work?
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{ margin-bottom:0;
}
This works on a shell (bash, dash) prompt:
[ -z "" ] && echo A || echo B
A
However, I am trying to write a POSIX shell script, it starts like this:
#!/bin/sh
[ "${#}" -eq 1 ] || echo "Invalid number of arguments, expected one."; exit 1
readonly raw_input_string=${1}
[ -z "${raw_input_string}" ] && echo "The given argument is empty."; exit 1
And I don't know why, but I don't get the message:
The given argument is empty.
if I call the script like this:
./test_empty_argument ""
Why is that?
shell-script arguments
|
show 3 more comments
This works on a shell (bash, dash) prompt:
[ -z "" ] && echo A || echo B
A
However, I am trying to write a POSIX shell script, it starts like this:
#!/bin/sh
[ "${#}" -eq 1 ] || echo "Invalid number of arguments, expected one."; exit 1
readonly raw_input_string=${1}
[ -z "${raw_input_string}" ] && echo "The given argument is empty."; exit 1
And I don't know why, but I don't get the message:
The given argument is empty.
if I call the script like this:
./test_empty_argument ""
Why is that?
shell-script arguments
5
See How can I test if a variable is empty or contains only spaces? for ways on testing if a variable is empty, unset, or only contains blanks. The issue in this question has nothing to do with that.
– ilkkachu
Apr 3 at 17:12
1
Just useif [ X”” = X”$var” ] ; then echo isempty ; fi
– user2497
Apr 3 at 17:37
3
@user2497 There is no reason to use that in any shell released in the last 20 years. That's a workaround for old, buggy shells.
– chepner
Apr 3 at 18:11
@chepner So it is not a valid solution? Something else must be used?
– user2497
Apr 3 at 18:31
6
[ "" = "$var" ]
would work fine; a quoted empty string will not be removed from the argument list of[
. But that's not necessary either, because[ -z "$var" ]
also works just fine.
– chepner
Apr 3 at 18:50
|
show 3 more comments
This works on a shell (bash, dash) prompt:
[ -z "" ] && echo A || echo B
A
However, I am trying to write a POSIX shell script, it starts like this:
#!/bin/sh
[ "${#}" -eq 1 ] || echo "Invalid number of arguments, expected one."; exit 1
readonly raw_input_string=${1}
[ -z "${raw_input_string}" ] && echo "The given argument is empty."; exit 1
And I don't know why, but I don't get the message:
The given argument is empty.
if I call the script like this:
./test_empty_argument ""
Why is that?
shell-script arguments
This works on a shell (bash, dash) prompt:
[ -z "" ] && echo A || echo B
A
However, I am trying to write a POSIX shell script, it starts like this:
#!/bin/sh
[ "${#}" -eq 1 ] || echo "Invalid number of arguments, expected one."; exit 1
readonly raw_input_string=${1}
[ -z "${raw_input_string}" ] && echo "The given argument is empty."; exit 1
And I don't know why, but I don't get the message:
The given argument is empty.
if I call the script like this:
./test_empty_argument ""
Why is that?
shell-script arguments
shell-script arguments
edited Apr 3 at 20:40
ilkkachu
63.3k10104181
63.3k10104181
asked Apr 3 at 6:41
VlastimilVlastimil
8,5631566148
8,5631566148
5
See How can I test if a variable is empty or contains only spaces? for ways on testing if a variable is empty, unset, or only contains blanks. The issue in this question has nothing to do with that.
– ilkkachu
Apr 3 at 17:12
1
Just useif [ X”” = X”$var” ] ; then echo isempty ; fi
– user2497
Apr 3 at 17:37
3
@user2497 There is no reason to use that in any shell released in the last 20 years. That's a workaround for old, buggy shells.
– chepner
Apr 3 at 18:11
@chepner So it is not a valid solution? Something else must be used?
– user2497
Apr 3 at 18:31
6
[ "" = "$var" ]
would work fine; a quoted empty string will not be removed from the argument list of[
. But that's not necessary either, because[ -z "$var" ]
also works just fine.
– chepner
Apr 3 at 18:50
|
show 3 more comments
5
See How can I test if a variable is empty or contains only spaces? for ways on testing if a variable is empty, unset, or only contains blanks. The issue in this question has nothing to do with that.
– ilkkachu
Apr 3 at 17:12
1
Just useif [ X”” = X”$var” ] ; then echo isempty ; fi
– user2497
Apr 3 at 17:37
3
@user2497 There is no reason to use that in any shell released in the last 20 years. That's a workaround for old, buggy shells.
– chepner
Apr 3 at 18:11
@chepner So it is not a valid solution? Something else must be used?
– user2497
Apr 3 at 18:31
6
[ "" = "$var" ]
would work fine; a quoted empty string will not be removed from the argument list of[
. But that's not necessary either, because[ -z "$var" ]
also works just fine.
– chepner
Apr 3 at 18:50
5
5
See How can I test if a variable is empty or contains only spaces? for ways on testing if a variable is empty, unset, or only contains blanks. The issue in this question has nothing to do with that.
– ilkkachu
Apr 3 at 17:12
See How can I test if a variable is empty or contains only spaces? for ways on testing if a variable is empty, unset, or only contains blanks. The issue in this question has nothing to do with that.
– ilkkachu
Apr 3 at 17:12
1
1
Just use
if [ X”” = X”$var” ] ; then echo isempty ; fi
– user2497
Apr 3 at 17:37
Just use
if [ X”” = X”$var” ] ; then echo isempty ; fi
– user2497
Apr 3 at 17:37
3
3
@user2497 There is no reason to use that in any shell released in the last 20 years. That's a workaround for old, buggy shells.
– chepner
Apr 3 at 18:11
@user2497 There is no reason to use that in any shell released in the last 20 years. That's a workaround for old, buggy shells.
– chepner
Apr 3 at 18:11
@chepner So it is not a valid solution? Something else must be used?
– user2497
Apr 3 at 18:31
@chepner So it is not a valid solution? Something else must be used?
– user2497
Apr 3 at 18:31
6
6
[ "" = "$var" ]
would work fine; a quoted empty string will not be removed from the argument list of [
. But that's not necessary either, because [ -z "$var" ]
also works just fine.– chepner
Apr 3 at 18:50
[ "" = "$var" ]
would work fine; a quoted empty string will not be removed from the argument list of [
. But that's not necessary either, because [ -z "$var" ]
also works just fine.– chepner
Apr 3 at 18:50
|
show 3 more comments
4 Answers
4
active
oldest
votes
Note that your line
[ "${#}" -eq 1 ] || echo "Invalid number of arguments, expected one."; exit 1
this is the same as
[ "${#}" -eq 1 ] || echo "Invalid number of arguments, expected one."
exit 1
(an unquoted ;
can, in most circumstances, be replaced by a newline character)
This means that the exit 1
statement is always executed regardless of how many arguments were passed to the script. This in turn means that the message The given argument is empty.
would never have a chance of getting printed.
To execute more than a single statement after a test using the "short-circuit syntax", group the statements in { ...; }
. The alternative is to use a proper if
statement (which, IMHO, looks cleaner in a script):
if [ "$#" -ne 1 ]; then
echo 'Invalid number of arguments, expected one.' >&2
exit 1
fi
You have the same issue with your second test.
Regarding
[ -z "" ] && echo A || echo B
This would work for the given example, but the generic
some-test && command1 || command2
would not be the same as
if some-test; then
command1
else
command2
fi
Instead, it is more like
if ! { some-test && command1; }; then
command2
fi
That is, if either the test or the first command fails, the second command executes, which means it has the potential to execute all three involved statements.
add a comment |
This:
[ "${#}" -eq 1 ] || echo "Invalid number of arguments, expected one."; exit 1
is not:
[ "${#}" -eq 1 ] || { echo "Invalid number of arguments, expected one."; exit 1; }
But instead is:
{ [ "${#}" -eq 1 ] || echo "Invalid number of arguments, expected one."; }
exit 1
Your script is exiting regardless of how many arguments you passed to it.
add a comment |
One way to make it more readable is to define a die
function (à la perl
) like:
die() {
printf >&2 '%sn' "$@"
exit 1
}
# then:
[ "$#" -eq 1 ] || die "Expected one argument, got $#"
[ -n "$1" ] || die "Empty argument not supported"
You can add more bells and whistles like colours, prefix, line number... if need be.
In practice, do you ever call yourdie
function with multiple arguments? (If so, can you give an example?) I use an almost identicaldie
function, but use"$*"
instead, which may be more what you're intending?
– jrw32982
Apr 3 at 18:15
3
The value of"$@"
is that it allows multi-line messages without needing to add literal newlines.
– Charles Duffy
Apr 3 at 20:54
1
@jrw32982, using"$*"
to join args with spaces also means you need to set$IFS
to SPC for it to work in all contexts including those where$IFS
has been modified. Alternatively withksh
/zsh
, you can useprint -r -- "$@"
orecho -E - "$@"
inzsh
.
– Stéphane Chazelas
Apr 4 at 7:17
@CharlesDuffy Yes, but I've never seen that done in the context of adie
-type function. What I'm asking is: in practice, have you ever seen anyone writedie "unable to blah:" "some error"
, for the purpose of getting a 2-line error message?
– jrw32982
Apr 4 at 13:24
@StéphaneChazelas Good point. So (in my formulation) it should bedie() { IFS=" "; printf >&2 "%sn" "$*"; exit 1; }
. Have you ever personally used this kind ofdie
function to haveprintf
generate a multi-line error message by passing multiple arguments? Or do you only ever pass a single argument todie
so that it only adds a single newline to its output?
– jrw32982
Apr 4 at 13:29
|
show 3 more comments
I've often seen this as a test for an empty string:
if [ "x$foo" = "x" ]; then ...
Should have been "=" - fixed.
– wef
Apr 3 at 6:56
3
That practice is literally from the 1970s. There is no reason whatsoever to use it with any shell that is compliant with the 1992 POSIX sh standard (so long as correct quoting is used and now-obsolescent functionality such as-a
,-o
,(
and)
as derectives to telltest
to combine multiple operations in a single invocation are avoided; see the OB markers in pubs.opengroup.org/onlinepubs/9699919799/utilities/test.html).
– Charles Duffy
Apr 3 at 20:52
Non-linux unices shipped with the original 'sh' well into the '90's - maybe still do. In my job at that time, I had to write portable install scripts and I used this construct. I just looked at the install scripts that NVidia ships for linux and they still use this construct.
– wef
Apr 3 at 22:21
NVidia may use it, but that's not to say they have any technical justification to do so; cargo-cult development in commercial UNIX is sadly prevalent. Even Heirloom Bourne doesn't have the bug in question -- so the SunOS codebase (that being the last commercial UNIX to ship a non-POSIX/bin/sh
, and Heirloom Bourne's immediate predecessor) didn't have it either.
– Charles Duffy
Apr 3 at 23:13
1
I don't wear a hat, so I can't promise to post a YouTube video eating it should someone turn up a shell published on a commercial UNIX with this bug post-1990... but if I did, it would be tempting. :)
– Charles Duffy
Apr 3 at 23:32
add a comment |
Your Answer
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "106"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f510216%2fwhy-doesnt-using-multiple-commands-with-a-or-conditional-work%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
4 Answers
4
active
oldest
votes
4 Answers
4
active
oldest
votes
active
oldest
votes
active
oldest
votes
Note that your line
[ "${#}" -eq 1 ] || echo "Invalid number of arguments, expected one."; exit 1
this is the same as
[ "${#}" -eq 1 ] || echo "Invalid number of arguments, expected one."
exit 1
(an unquoted ;
can, in most circumstances, be replaced by a newline character)
This means that the exit 1
statement is always executed regardless of how many arguments were passed to the script. This in turn means that the message The given argument is empty.
would never have a chance of getting printed.
To execute more than a single statement after a test using the "short-circuit syntax", group the statements in { ...; }
. The alternative is to use a proper if
statement (which, IMHO, looks cleaner in a script):
if [ "$#" -ne 1 ]; then
echo 'Invalid number of arguments, expected one.' >&2
exit 1
fi
You have the same issue with your second test.
Regarding
[ -z "" ] && echo A || echo B
This would work for the given example, but the generic
some-test && command1 || command2
would not be the same as
if some-test; then
command1
else
command2
fi
Instead, it is more like
if ! { some-test && command1; }; then
command2
fi
That is, if either the test or the first command fails, the second command executes, which means it has the potential to execute all three involved statements.
add a comment |
Note that your line
[ "${#}" -eq 1 ] || echo "Invalid number of arguments, expected one."; exit 1
this is the same as
[ "${#}" -eq 1 ] || echo "Invalid number of arguments, expected one."
exit 1
(an unquoted ;
can, in most circumstances, be replaced by a newline character)
This means that the exit 1
statement is always executed regardless of how many arguments were passed to the script. This in turn means that the message The given argument is empty.
would never have a chance of getting printed.
To execute more than a single statement after a test using the "short-circuit syntax", group the statements in { ...; }
. The alternative is to use a proper if
statement (which, IMHO, looks cleaner in a script):
if [ "$#" -ne 1 ]; then
echo 'Invalid number of arguments, expected one.' >&2
exit 1
fi
You have the same issue with your second test.
Regarding
[ -z "" ] && echo A || echo B
This would work for the given example, but the generic
some-test && command1 || command2
would not be the same as
if some-test; then
command1
else
command2
fi
Instead, it is more like
if ! { some-test && command1; }; then
command2
fi
That is, if either the test or the first command fails, the second command executes, which means it has the potential to execute all three involved statements.
add a comment |
Note that your line
[ "${#}" -eq 1 ] || echo "Invalid number of arguments, expected one."; exit 1
this is the same as
[ "${#}" -eq 1 ] || echo "Invalid number of arguments, expected one."
exit 1
(an unquoted ;
can, in most circumstances, be replaced by a newline character)
This means that the exit 1
statement is always executed regardless of how many arguments were passed to the script. This in turn means that the message The given argument is empty.
would never have a chance of getting printed.
To execute more than a single statement after a test using the "short-circuit syntax", group the statements in { ...; }
. The alternative is to use a proper if
statement (which, IMHO, looks cleaner in a script):
if [ "$#" -ne 1 ]; then
echo 'Invalid number of arguments, expected one.' >&2
exit 1
fi
You have the same issue with your second test.
Regarding
[ -z "" ] && echo A || echo B
This would work for the given example, but the generic
some-test && command1 || command2
would not be the same as
if some-test; then
command1
else
command2
fi
Instead, it is more like
if ! { some-test && command1; }; then
command2
fi
That is, if either the test or the first command fails, the second command executes, which means it has the potential to execute all three involved statements.
Note that your line
[ "${#}" -eq 1 ] || echo "Invalid number of arguments, expected one."; exit 1
this is the same as
[ "${#}" -eq 1 ] || echo "Invalid number of arguments, expected one."
exit 1
(an unquoted ;
can, in most circumstances, be replaced by a newline character)
This means that the exit 1
statement is always executed regardless of how many arguments were passed to the script. This in turn means that the message The given argument is empty.
would never have a chance of getting printed.
To execute more than a single statement after a test using the "short-circuit syntax", group the statements in { ...; }
. The alternative is to use a proper if
statement (which, IMHO, looks cleaner in a script):
if [ "$#" -ne 1 ]; then
echo 'Invalid number of arguments, expected one.' >&2
exit 1
fi
You have the same issue with your second test.
Regarding
[ -z "" ] && echo A || echo B
This would work for the given example, but the generic
some-test && command1 || command2
would not be the same as
if some-test; then
command1
else
command2
fi
Instead, it is more like
if ! { some-test && command1; }; then
command2
fi
That is, if either the test or the first command fails, the second command executes, which means it has the potential to execute all three involved statements.
edited Apr 4 at 6:33
answered Apr 3 at 6:48
Kusalananda♦Kusalananda
140k17261436
140k17261436
add a comment |
add a comment |
This:
[ "${#}" -eq 1 ] || echo "Invalid number of arguments, expected one."; exit 1
is not:
[ "${#}" -eq 1 ] || { echo "Invalid number of arguments, expected one."; exit 1; }
But instead is:
{ [ "${#}" -eq 1 ] || echo "Invalid number of arguments, expected one."; }
exit 1
Your script is exiting regardless of how many arguments you passed to it.
add a comment |
This:
[ "${#}" -eq 1 ] || echo "Invalid number of arguments, expected one."; exit 1
is not:
[ "${#}" -eq 1 ] || { echo "Invalid number of arguments, expected one."; exit 1; }
But instead is:
{ [ "${#}" -eq 1 ] || echo "Invalid number of arguments, expected one."; }
exit 1
Your script is exiting regardless of how many arguments you passed to it.
add a comment |
This:
[ "${#}" -eq 1 ] || echo "Invalid number of arguments, expected one."; exit 1
is not:
[ "${#}" -eq 1 ] || { echo "Invalid number of arguments, expected one."; exit 1; }
But instead is:
{ [ "${#}" -eq 1 ] || echo "Invalid number of arguments, expected one."; }
exit 1
Your script is exiting regardless of how many arguments you passed to it.
This:
[ "${#}" -eq 1 ] || echo "Invalid number of arguments, expected one."; exit 1
is not:
[ "${#}" -eq 1 ] || { echo "Invalid number of arguments, expected one."; exit 1; }
But instead is:
{ [ "${#}" -eq 1 ] || echo "Invalid number of arguments, expected one."; }
exit 1
Your script is exiting regardless of how many arguments you passed to it.
answered Apr 3 at 6:46
murumuru
37.3k589164
37.3k589164
add a comment |
add a comment |
One way to make it more readable is to define a die
function (à la perl
) like:
die() {
printf >&2 '%sn' "$@"
exit 1
}
# then:
[ "$#" -eq 1 ] || die "Expected one argument, got $#"
[ -n "$1" ] || die "Empty argument not supported"
You can add more bells and whistles like colours, prefix, line number... if need be.
In practice, do you ever call yourdie
function with multiple arguments? (If so, can you give an example?) I use an almost identicaldie
function, but use"$*"
instead, which may be more what you're intending?
– jrw32982
Apr 3 at 18:15
3
The value of"$@"
is that it allows multi-line messages without needing to add literal newlines.
– Charles Duffy
Apr 3 at 20:54
1
@jrw32982, using"$*"
to join args with spaces also means you need to set$IFS
to SPC for it to work in all contexts including those where$IFS
has been modified. Alternatively withksh
/zsh
, you can useprint -r -- "$@"
orecho -E - "$@"
inzsh
.
– Stéphane Chazelas
Apr 4 at 7:17
@CharlesDuffy Yes, but I've never seen that done in the context of adie
-type function. What I'm asking is: in practice, have you ever seen anyone writedie "unable to blah:" "some error"
, for the purpose of getting a 2-line error message?
– jrw32982
Apr 4 at 13:24
@StéphaneChazelas Good point. So (in my formulation) it should bedie() { IFS=" "; printf >&2 "%sn" "$*"; exit 1; }
. Have you ever personally used this kind ofdie
function to haveprintf
generate a multi-line error message by passing multiple arguments? Or do you only ever pass a single argument todie
so that it only adds a single newline to its output?
– jrw32982
Apr 4 at 13:29
|
show 3 more comments
One way to make it more readable is to define a die
function (à la perl
) like:
die() {
printf >&2 '%sn' "$@"
exit 1
}
# then:
[ "$#" -eq 1 ] || die "Expected one argument, got $#"
[ -n "$1" ] || die "Empty argument not supported"
You can add more bells and whistles like colours, prefix, line number... if need be.
In practice, do you ever call yourdie
function with multiple arguments? (If so, can you give an example?) I use an almost identicaldie
function, but use"$*"
instead, which may be more what you're intending?
– jrw32982
Apr 3 at 18:15
3
The value of"$@"
is that it allows multi-line messages without needing to add literal newlines.
– Charles Duffy
Apr 3 at 20:54
1
@jrw32982, using"$*"
to join args with spaces also means you need to set$IFS
to SPC for it to work in all contexts including those where$IFS
has been modified. Alternatively withksh
/zsh
, you can useprint -r -- "$@"
orecho -E - "$@"
inzsh
.
– Stéphane Chazelas
Apr 4 at 7:17
@CharlesDuffy Yes, but I've never seen that done in the context of adie
-type function. What I'm asking is: in practice, have you ever seen anyone writedie "unable to blah:" "some error"
, for the purpose of getting a 2-line error message?
– jrw32982
Apr 4 at 13:24
@StéphaneChazelas Good point. So (in my formulation) it should bedie() { IFS=" "; printf >&2 "%sn" "$*"; exit 1; }
. Have you ever personally used this kind ofdie
function to haveprintf
generate a multi-line error message by passing multiple arguments? Or do you only ever pass a single argument todie
so that it only adds a single newline to its output?
– jrw32982
Apr 4 at 13:29
|
show 3 more comments
One way to make it more readable is to define a die
function (à la perl
) like:
die() {
printf >&2 '%sn' "$@"
exit 1
}
# then:
[ "$#" -eq 1 ] || die "Expected one argument, got $#"
[ -n "$1" ] || die "Empty argument not supported"
You can add more bells and whistles like colours, prefix, line number... if need be.
One way to make it more readable is to define a die
function (à la perl
) like:
die() {
printf >&2 '%sn' "$@"
exit 1
}
# then:
[ "$#" -eq 1 ] || die "Expected one argument, got $#"
[ -n "$1" ] || die "Empty argument not supported"
You can add more bells and whistles like colours, prefix, line number... if need be.
edited Apr 4 at 13:35
answered Apr 3 at 16:53
Stéphane ChazelasStéphane Chazelas
313k57593950
313k57593950
In practice, do you ever call yourdie
function with multiple arguments? (If so, can you give an example?) I use an almost identicaldie
function, but use"$*"
instead, which may be more what you're intending?
– jrw32982
Apr 3 at 18:15
3
The value of"$@"
is that it allows multi-line messages without needing to add literal newlines.
– Charles Duffy
Apr 3 at 20:54
1
@jrw32982, using"$*"
to join args with spaces also means you need to set$IFS
to SPC for it to work in all contexts including those where$IFS
has been modified. Alternatively withksh
/zsh
, you can useprint -r -- "$@"
orecho -E - "$@"
inzsh
.
– Stéphane Chazelas
Apr 4 at 7:17
@CharlesDuffy Yes, but I've never seen that done in the context of adie
-type function. What I'm asking is: in practice, have you ever seen anyone writedie "unable to blah:" "some error"
, for the purpose of getting a 2-line error message?
– jrw32982
Apr 4 at 13:24
@StéphaneChazelas Good point. So (in my formulation) it should bedie() { IFS=" "; printf >&2 "%sn" "$*"; exit 1; }
. Have you ever personally used this kind ofdie
function to haveprintf
generate a multi-line error message by passing multiple arguments? Or do you only ever pass a single argument todie
so that it only adds a single newline to its output?
– jrw32982
Apr 4 at 13:29
|
show 3 more comments
In practice, do you ever call yourdie
function with multiple arguments? (If so, can you give an example?) I use an almost identicaldie
function, but use"$*"
instead, which may be more what you're intending?
– jrw32982
Apr 3 at 18:15
3
The value of"$@"
is that it allows multi-line messages without needing to add literal newlines.
– Charles Duffy
Apr 3 at 20:54
1
@jrw32982, using"$*"
to join args with spaces also means you need to set$IFS
to SPC for it to work in all contexts including those where$IFS
has been modified. Alternatively withksh
/zsh
, you can useprint -r -- "$@"
orecho -E - "$@"
inzsh
.
– Stéphane Chazelas
Apr 4 at 7:17
@CharlesDuffy Yes, but I've never seen that done in the context of adie
-type function. What I'm asking is: in practice, have you ever seen anyone writedie "unable to blah:" "some error"
, for the purpose of getting a 2-line error message?
– jrw32982
Apr 4 at 13:24
@StéphaneChazelas Good point. So (in my formulation) it should bedie() { IFS=" "; printf >&2 "%sn" "$*"; exit 1; }
. Have you ever personally used this kind ofdie
function to haveprintf
generate a multi-line error message by passing multiple arguments? Or do you only ever pass a single argument todie
so that it only adds a single newline to its output?
– jrw32982
Apr 4 at 13:29
In practice, do you ever call your
die
function with multiple arguments? (If so, can you give an example?) I use an almost identical die
function, but use "$*"
instead, which may be more what you're intending?– jrw32982
Apr 3 at 18:15
In practice, do you ever call your
die
function with multiple arguments? (If so, can you give an example?) I use an almost identical die
function, but use "$*"
instead, which may be more what you're intending?– jrw32982
Apr 3 at 18:15
3
3
The value of
"$@"
is that it allows multi-line messages without needing to add literal newlines.– Charles Duffy
Apr 3 at 20:54
The value of
"$@"
is that it allows multi-line messages without needing to add literal newlines.– Charles Duffy
Apr 3 at 20:54
1
1
@jrw32982, using
"$*"
to join args with spaces also means you need to set $IFS
to SPC for it to work in all contexts including those where $IFS
has been modified. Alternatively with ksh
/zsh
, you can use print -r -- "$@"
or echo -E - "$@"
in zsh
.– Stéphane Chazelas
Apr 4 at 7:17
@jrw32982, using
"$*"
to join args with spaces also means you need to set $IFS
to SPC for it to work in all contexts including those where $IFS
has been modified. Alternatively with ksh
/zsh
, you can use print -r -- "$@"
or echo -E - "$@"
in zsh
.– Stéphane Chazelas
Apr 4 at 7:17
@CharlesDuffy Yes, but I've never seen that done in the context of a
die
-type function. What I'm asking is: in practice, have you ever seen anyone write die "unable to blah:" "some error"
, for the purpose of getting a 2-line error message?– jrw32982
Apr 4 at 13:24
@CharlesDuffy Yes, but I've never seen that done in the context of a
die
-type function. What I'm asking is: in practice, have you ever seen anyone write die "unable to blah:" "some error"
, for the purpose of getting a 2-line error message?– jrw32982
Apr 4 at 13:24
@StéphaneChazelas Good point. So (in my formulation) it should be
die() { IFS=" "; printf >&2 "%sn" "$*"; exit 1; }
. Have you ever personally used this kind of die
function to have printf
generate a multi-line error message by passing multiple arguments? Or do you only ever pass a single argument to die
so that it only adds a single newline to its output?– jrw32982
Apr 4 at 13:29
@StéphaneChazelas Good point. So (in my formulation) it should be
die() { IFS=" "; printf >&2 "%sn" "$*"; exit 1; }
. Have you ever personally used this kind of die
function to have printf
generate a multi-line error message by passing multiple arguments? Or do you only ever pass a single argument to die
so that it only adds a single newline to its output?– jrw32982
Apr 4 at 13:29
|
show 3 more comments
I've often seen this as a test for an empty string:
if [ "x$foo" = "x" ]; then ...
Should have been "=" - fixed.
– wef
Apr 3 at 6:56
3
That practice is literally from the 1970s. There is no reason whatsoever to use it with any shell that is compliant with the 1992 POSIX sh standard (so long as correct quoting is used and now-obsolescent functionality such as-a
,-o
,(
and)
as derectives to telltest
to combine multiple operations in a single invocation are avoided; see the OB markers in pubs.opengroup.org/onlinepubs/9699919799/utilities/test.html).
– Charles Duffy
Apr 3 at 20:52
Non-linux unices shipped with the original 'sh' well into the '90's - maybe still do. In my job at that time, I had to write portable install scripts and I used this construct. I just looked at the install scripts that NVidia ships for linux and they still use this construct.
– wef
Apr 3 at 22:21
NVidia may use it, but that's not to say they have any technical justification to do so; cargo-cult development in commercial UNIX is sadly prevalent. Even Heirloom Bourne doesn't have the bug in question -- so the SunOS codebase (that being the last commercial UNIX to ship a non-POSIX/bin/sh
, and Heirloom Bourne's immediate predecessor) didn't have it either.
– Charles Duffy
Apr 3 at 23:13
1
I don't wear a hat, so I can't promise to post a YouTube video eating it should someone turn up a shell published on a commercial UNIX with this bug post-1990... but if I did, it would be tempting. :)
– Charles Duffy
Apr 3 at 23:32
add a comment |
I've often seen this as a test for an empty string:
if [ "x$foo" = "x" ]; then ...
Should have been "=" - fixed.
– wef
Apr 3 at 6:56
3
That practice is literally from the 1970s. There is no reason whatsoever to use it with any shell that is compliant with the 1992 POSIX sh standard (so long as correct quoting is used and now-obsolescent functionality such as-a
,-o
,(
and)
as derectives to telltest
to combine multiple operations in a single invocation are avoided; see the OB markers in pubs.opengroup.org/onlinepubs/9699919799/utilities/test.html).
– Charles Duffy
Apr 3 at 20:52
Non-linux unices shipped with the original 'sh' well into the '90's - maybe still do. In my job at that time, I had to write portable install scripts and I used this construct. I just looked at the install scripts that NVidia ships for linux and they still use this construct.
– wef
Apr 3 at 22:21
NVidia may use it, but that's not to say they have any technical justification to do so; cargo-cult development in commercial UNIX is sadly prevalent. Even Heirloom Bourne doesn't have the bug in question -- so the SunOS codebase (that being the last commercial UNIX to ship a non-POSIX/bin/sh
, and Heirloom Bourne's immediate predecessor) didn't have it either.
– Charles Duffy
Apr 3 at 23:13
1
I don't wear a hat, so I can't promise to post a YouTube video eating it should someone turn up a shell published on a commercial UNIX with this bug post-1990... but if I did, it would be tempting. :)
– Charles Duffy
Apr 3 at 23:32
add a comment |
I've often seen this as a test for an empty string:
if [ "x$foo" = "x" ]; then ...
I've often seen this as a test for an empty string:
if [ "x$foo" = "x" ]; then ...
edited Apr 3 at 6:55
answered Apr 3 at 6:54
wefwef
31215
31215
Should have been "=" - fixed.
– wef
Apr 3 at 6:56
3
That practice is literally from the 1970s. There is no reason whatsoever to use it with any shell that is compliant with the 1992 POSIX sh standard (so long as correct quoting is used and now-obsolescent functionality such as-a
,-o
,(
and)
as derectives to telltest
to combine multiple operations in a single invocation are avoided; see the OB markers in pubs.opengroup.org/onlinepubs/9699919799/utilities/test.html).
– Charles Duffy
Apr 3 at 20:52
Non-linux unices shipped with the original 'sh' well into the '90's - maybe still do. In my job at that time, I had to write portable install scripts and I used this construct. I just looked at the install scripts that NVidia ships for linux and they still use this construct.
– wef
Apr 3 at 22:21
NVidia may use it, but that's not to say they have any technical justification to do so; cargo-cult development in commercial UNIX is sadly prevalent. Even Heirloom Bourne doesn't have the bug in question -- so the SunOS codebase (that being the last commercial UNIX to ship a non-POSIX/bin/sh
, and Heirloom Bourne's immediate predecessor) didn't have it either.
– Charles Duffy
Apr 3 at 23:13
1
I don't wear a hat, so I can't promise to post a YouTube video eating it should someone turn up a shell published on a commercial UNIX with this bug post-1990... but if I did, it would be tempting. :)
– Charles Duffy
Apr 3 at 23:32
add a comment |
Should have been "=" - fixed.
– wef
Apr 3 at 6:56
3
That practice is literally from the 1970s. There is no reason whatsoever to use it with any shell that is compliant with the 1992 POSIX sh standard (so long as correct quoting is used and now-obsolescent functionality such as-a
,-o
,(
and)
as derectives to telltest
to combine multiple operations in a single invocation are avoided; see the OB markers in pubs.opengroup.org/onlinepubs/9699919799/utilities/test.html).
– Charles Duffy
Apr 3 at 20:52
Non-linux unices shipped with the original 'sh' well into the '90's - maybe still do. In my job at that time, I had to write portable install scripts and I used this construct. I just looked at the install scripts that NVidia ships for linux and they still use this construct.
– wef
Apr 3 at 22:21
NVidia may use it, but that's not to say they have any technical justification to do so; cargo-cult development in commercial UNIX is sadly prevalent. Even Heirloom Bourne doesn't have the bug in question -- so the SunOS codebase (that being the last commercial UNIX to ship a non-POSIX/bin/sh
, and Heirloom Bourne's immediate predecessor) didn't have it either.
– Charles Duffy
Apr 3 at 23:13
1
I don't wear a hat, so I can't promise to post a YouTube video eating it should someone turn up a shell published on a commercial UNIX with this bug post-1990... but if I did, it would be tempting. :)
– Charles Duffy
Apr 3 at 23:32
Should have been "=" - fixed.
– wef
Apr 3 at 6:56
Should have been "=" - fixed.
– wef
Apr 3 at 6:56
3
3
That practice is literally from the 1970s. There is no reason whatsoever to use it with any shell that is compliant with the 1992 POSIX sh standard (so long as correct quoting is used and now-obsolescent functionality such as
-a
, -o
, (
and )
as derectives to tell test
to combine multiple operations in a single invocation are avoided; see the OB markers in pubs.opengroup.org/onlinepubs/9699919799/utilities/test.html).– Charles Duffy
Apr 3 at 20:52
That practice is literally from the 1970s. There is no reason whatsoever to use it with any shell that is compliant with the 1992 POSIX sh standard (so long as correct quoting is used and now-obsolescent functionality such as
-a
, -o
, (
and )
as derectives to tell test
to combine multiple operations in a single invocation are avoided; see the OB markers in pubs.opengroup.org/onlinepubs/9699919799/utilities/test.html).– Charles Duffy
Apr 3 at 20:52
Non-linux unices shipped with the original 'sh' well into the '90's - maybe still do. In my job at that time, I had to write portable install scripts and I used this construct. I just looked at the install scripts that NVidia ships for linux and they still use this construct.
– wef
Apr 3 at 22:21
Non-linux unices shipped with the original 'sh' well into the '90's - maybe still do. In my job at that time, I had to write portable install scripts and I used this construct. I just looked at the install scripts that NVidia ships for linux and they still use this construct.
– wef
Apr 3 at 22:21
NVidia may use it, but that's not to say they have any technical justification to do so; cargo-cult development in commercial UNIX is sadly prevalent. Even Heirloom Bourne doesn't have the bug in question -- so the SunOS codebase (that being the last commercial UNIX to ship a non-POSIX
/bin/sh
, and Heirloom Bourne's immediate predecessor) didn't have it either.– Charles Duffy
Apr 3 at 23:13
NVidia may use it, but that's not to say they have any technical justification to do so; cargo-cult development in commercial UNIX is sadly prevalent. Even Heirloom Bourne doesn't have the bug in question -- so the SunOS codebase (that being the last commercial UNIX to ship a non-POSIX
/bin/sh
, and Heirloom Bourne's immediate predecessor) didn't have it either.– Charles Duffy
Apr 3 at 23:13
1
1
I don't wear a hat, so I can't promise to post a YouTube video eating it should someone turn up a shell published on a commercial UNIX with this bug post-1990... but if I did, it would be tempting. :)
– Charles Duffy
Apr 3 at 23:32
I don't wear a hat, so I can't promise to post a YouTube video eating it should someone turn up a shell published on a commercial UNIX with this bug post-1990... but if I did, it would be tempting. :)
– Charles Duffy
Apr 3 at 23:32
add a comment |
Thanks for contributing an answer to Unix & Linux Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f510216%2fwhy-doesnt-using-multiple-commands-with-a-or-conditional-work%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
5
See How can I test if a variable is empty or contains only spaces? for ways on testing if a variable is empty, unset, or only contains blanks. The issue in this question has nothing to do with that.
– ilkkachu
Apr 3 at 17:12
1
Just use
if [ X”” = X”$var” ] ; then echo isempty ; fi
– user2497
Apr 3 at 17:37
3
@user2497 There is no reason to use that in any shell released in the last 20 years. That's a workaround for old, buggy shells.
– chepner
Apr 3 at 18:11
@chepner So it is not a valid solution? Something else must be used?
– user2497
Apr 3 at 18:31
6
[ "" = "$var" ]
would work fine; a quoted empty string will not be removed from the argument list of[
. But that's not necessary either, because[ -z "$var" ]
also works just fine.– chepner
Apr 3 at 18:50