Expansion with *.txt in the shell doesn't work if no .txt file existsBash prompt doesn't print until I interact with console againCreating a very simple upstart scriptWhy no shell expansion?Unique sorting: Redirect output to the same fileWindows FINDSTR Ubuntu equivalent to search .csvDo GUI based application execute shell commands in the background?Terminal closes immediately after trying to change shell script back to bashsource syntax errorWhy do I get different output from the same commands? (redirect and piping)txt to pcap file conversion using sed and xxd
“The Fourier transform cannot measure two phases at the same frequency.” Why not?
Tile the chessboard with four-colored triominoes
Could an areostationary satellite help locate asteroids?
Launch capabilities of GSLV Mark III
Why do proponents of guns oppose gun competency tests?
Can I enter a rental property without giving notice if I'm afraid a tenant may be hurt?
Plato and the knowledge of the forms
The meaning of "scale" in "because diversions scale so easily wealth becomes concentrated"
Does the length of a password for Wi-Fi affect speed?
Is there a way to improve my grade after graduation?
What are the function of EM and EN spaces?
Our group keeps dying during the Lost Mine of Phandelver campaign. What are we doing wrong?
Write The Shortest Program to Calculate Height of a Binary Tree
I was contacted by a private bank overseas to get my inheritance
Not been paid even after reminding the Treasurer; what should I do?
Repeated! Factorials!
Why do my fried eggs start browning very fast?
How to call made-up data?
What is the difference between these two share classes of an ETF?
Why did the US Airways Flight 1549 passengers stay on the wings?
Why does putting a dot after the URL remove login information?
Why should I "believe in" weak solutions to PDEs?
Does a 4 bladed prop have almost twice the thrust of a 2 bladed prop?
Do some languages mention the top limit of a range first?
Expansion with *.txt in the shell doesn't work if no .txt file exists
Bash prompt doesn't print until I interact with console againCreating a very simple upstart scriptWhy no shell expansion?Unique sorting: Redirect output to the same fileWindows FINDSTR Ubuntu equivalent to search .csvDo GUI based application execute shell commands in the background?Terminal closes immediately after trying to change shell script back to bashsource syntax errorWhy do I get different output from the same commands? (redirect and piping)txt to pcap file conversion using sed and xxd
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty margin-bottom:0;
I was playing around with expansion, and I noticed a peculiar behavior. I tried doing:
echo ./*.txt
And I didn't have any .txt file in my current directory. The output I got was:
./*.txt
I'm just curious: Why did I get this? I was expecting to not get any output.
PS: When I did have a .txt file, the expansion was correctly interpreted. In other words, say I had a file, smthn.txt, the echo actually echoed current_directory/smthn.txt.
command-line bash
add a comment |
I was playing around with expansion, and I noticed a peculiar behavior. I tried doing:
echo ./*.txt
And I didn't have any .txt file in my current directory. The output I got was:
./*.txt
I'm just curious: Why did I get this? I was expecting to not get any output.
PS: When I did have a .txt file, the expansion was correctly interpreted. In other words, say I had a file, smthn.txt, the echo actually echoed current_directory/smthn.txt.
command-line bash
add a comment |
I was playing around with expansion, and I noticed a peculiar behavior. I tried doing:
echo ./*.txt
And I didn't have any .txt file in my current directory. The output I got was:
./*.txt
I'm just curious: Why did I get this? I was expecting to not get any output.
PS: When I did have a .txt file, the expansion was correctly interpreted. In other words, say I had a file, smthn.txt, the echo actually echoed current_directory/smthn.txt.
command-line bash
I was playing around with expansion, and I noticed a peculiar behavior. I tried doing:
echo ./*.txt
And I didn't have any .txt file in my current directory. The output I got was:
./*.txt
I'm just curious: Why did I get this? I was expecting to not get any output.
PS: When I did have a .txt file, the expansion was correctly interpreted. In other words, say I had a file, smthn.txt, the echo actually echoed current_directory/smthn.txt.
command-line bash
command-line bash
edited Jul 27 at 13:20
Peter Mortensen
1,0272 gold badges11 silver badges17 bronze badges
1,0272 gold badges11 silver badges17 bronze badges
asked Jul 26 at 8:45
user10796158user10796158
1775 bronze badges
1775 bronze badges
add a comment |
add a comment |
3 Answers
3
active
oldest
votes
Adapting from the bash shell man page,
bash scans each word for the characters *, ?, and [. If one of
these characters appears, then the word is regarded as a pattern, and
replaced with an alphabetically sorted list of filenames matching
the pattern. If no matching filenames are found, and the shell
option nullglob is not enabled, the word is left unchanged. If the
nullglob option is set, and no matches are found, the word is
removed.
In this case I presume nullglob is not enabled, so the word is left unchanged - hence the output you see.
2
You can change the behaviour as follows:shopt -s nullglobwill yield empty strings for unmatched patterns andshopt -u nullglob(standard setting) will yield the pattern itself.
– PerlDuck
Jul 26 at 9:03
add a comment |
I was expecting to not get any output.
If nullglob were the default, many commands would behave quite unexpectedly, because it is (perhaps unfortunately) common that commands treat the case of zero filename arguments in a qualitatively different way than the case of one or more filename arguments.
Suppose you've enabled nullglob (shopt -s nullglob) and you're in a directory where no files match *.txt. Then *.txt will indeed expand to nothing--not an empty field, but no fields at all--as you expected. But that would have these results:
ls *.txtwould list all the files in the current directory (except hidden files), because that's whatlsdoes when you don't pass it any filename arguments.cat *.txtwould read from standard input, because whencathas no filename arguments, it's as if you rancat -. If running interactively, it sits around waiting for input. Many commands behave this way.cp *.txt dest/would fail with the errorcp: missing destination file operand after 'dest/'. This isn't a disaster, but it's confusing and quite different from the silent success that is probably desired.file *.txt, and various other programs with no special behavior for the case of zero filename arguments, would still fail with an error or usage message when none are passed.- Even cases that intuitively feel like they should work often wouldn't.
printf 'Got file: "%s"n' *.txtwould printGot file: ""instead of nothing. - Accidental failure to quote occurrences of
*,?, and[that aren't intended to be expanded by the shell would more often produce obviously wrong results, but in ways that might be difficult to figure out. For example, if no filenames in the current directory started withgedit, thenapt list gedit*(whereapt list 'gedit*'was intended) would become justapt listand list all available packages.
So it's good that you don't get this behavior without requesting it. Probably the most common practical situation that is actually simplified by nullglob is for f in *.txt. See also this question (which Sergiy Kolodyazhnyy's answer linked to).
The harder question to answer is why failglob--where it's an expansion error to have a glob that doesn't match any files--isn't the default in bash. I believe Sergiy Kolodyazhnyy's answer captures the reason for this even without addressing it directly. Retaining unexpanding globs without producing an expansion error is (perhaps unfortunately) the standardized behavior, and it is also traditional, and thus expected, behavior. Although bash doesn't attempt to be fully POSIX-compliant unless it is invoked with the name sh or passed the --posix option, many of its design choices even when not in POSIX mode follow POSIX directly. They had to pick some behavior, and there are downsides associated with going against users' expectations.
I think this is the least historically influential aspect of the matter so I've saved it for last... but it is worth mentioning that there's something a bit conceptually odd about nullglob behavior.
nullglob seems elegant at first because, syntactically, it treats the case of zero matching files no differently from the case of one, two, or any other number. The commands we run, which globs expand into arguments for, don't tend to treat them the same, as detailed above. But syntactically this at least feels right, which I think is the motivation for your question.
And yet, there is another, more subtle inconsistency that nullglob doesn't address--that it actually amplifies. The case of zero globbing characters ("wildcards") is treated profoundly differently from that of one, or two, or any other number. For example, with shopt -s nullglob, if ab?d?f doesn't match any files, it is removed; if ab?d doesn't match any files, it is removed; but if ab doesn't match any files (i.e., if there is no file whose name is exactly ab) it is still not removed. Of course, it would be a disaster if it were removed, because it might not be intended to refer to an existing file in the current directory at all; it might not even refer to a file. But this still eliminates any hope for total consistency.
The three behaviors bash provides--the default of treating globs that don't match any files as though they weren't globs and passing them unexpanded, the behavior you expected of treating them (if you'll pardon this odd turn of phrase) as signifying all zero of the files that do match (nullglob), and the safe behavior of considering them errors (failglob)--all represent different approaches to the ambiguity inherent in the shell not being able to know if any particular word is intended to be a filename. The shell performs its expansions without knowledge of how the particular commands you call with it will treat their arguments.
This is one of many instances of separation of concerns. In systems whose design follows the Unix philosophy, each part is intended to do one thing and do it well. The shell processes text into commands and arguments and invokes those commands, most of which are external to the shell itself. This tends to be a lot nicer and more versatile than systems where the external commands are themselves responsible for performing those transformations (as with the traditional command processors in DOS and Windows). But it has its occasional downsides.
Apparently, bash-4.3.39(2) doesn't havefailglob. So it can't the default because it hasn't always been supported.
– Ruslan
Jul 28 at 6:48
add a comment |
The main reason is because this is standard behavior specified by POSIX - the standard which covers shell command language and among other things pattern matching ( shells such as bash, dash shell - Ubuntu's default /bin/sh, and ksh follow this standard ). From section 2.13.3 Patterns Used for Filename Expansion:
If the pattern does not match any existing filenames or pathnames, the pattern string shall be left unchanged.
This of course has a side effect - matching filename that may be literally *.txt. The nullglob option in bash and zsh can help: if that option is enabled via shopt -s nullglob (and it is not enabled by default which applies to this question), then globstar will be expanded to empty string when no matching filenames found. ksh93 has its own advanced pattern matching mechanism which achieves the same effect ~(N)*.txt
See also Why is nullglob not default?
add a comment |
Your Answer
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "89"
;
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: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
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%2faskubuntu.com%2fquestions%2f1161180%2fexpansion-with-txt-in-the-shell-doesnt-work-if-no-txt-file-exists%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
3 Answers
3
active
oldest
votes
3 Answers
3
active
oldest
votes
active
oldest
votes
active
oldest
votes
Adapting from the bash shell man page,
bash scans each word for the characters *, ?, and [. If one of
these characters appears, then the word is regarded as a pattern, and
replaced with an alphabetically sorted list of filenames matching
the pattern. If no matching filenames are found, and the shell
option nullglob is not enabled, the word is left unchanged. If the
nullglob option is set, and no matches are found, the word is
removed.
In this case I presume nullglob is not enabled, so the word is left unchanged - hence the output you see.
2
You can change the behaviour as follows:shopt -s nullglobwill yield empty strings for unmatched patterns andshopt -u nullglob(standard setting) will yield the pattern itself.
– PerlDuck
Jul 26 at 9:03
add a comment |
Adapting from the bash shell man page,
bash scans each word for the characters *, ?, and [. If one of
these characters appears, then the word is regarded as a pattern, and
replaced with an alphabetically sorted list of filenames matching
the pattern. If no matching filenames are found, and the shell
option nullglob is not enabled, the word is left unchanged. If the
nullglob option is set, and no matches are found, the word is
removed.
In this case I presume nullglob is not enabled, so the word is left unchanged - hence the output you see.
2
You can change the behaviour as follows:shopt -s nullglobwill yield empty strings for unmatched patterns andshopt -u nullglob(standard setting) will yield the pattern itself.
– PerlDuck
Jul 26 at 9:03
add a comment |
Adapting from the bash shell man page,
bash scans each word for the characters *, ?, and [. If one of
these characters appears, then the word is regarded as a pattern, and
replaced with an alphabetically sorted list of filenames matching
the pattern. If no matching filenames are found, and the shell
option nullglob is not enabled, the word is left unchanged. If the
nullglob option is set, and no matches are found, the word is
removed.
In this case I presume nullglob is not enabled, so the word is left unchanged - hence the output you see.
Adapting from the bash shell man page,
bash scans each word for the characters *, ?, and [. If one of
these characters appears, then the word is regarded as a pattern, and
replaced with an alphabetically sorted list of filenames matching
the pattern. If no matching filenames are found, and the shell
option nullglob is not enabled, the word is left unchanged. If the
nullglob option is set, and no matches are found, the word is
removed.
In this case I presume nullglob is not enabled, so the word is left unchanged - hence the output you see.
edited Jul 26 at 8:58
PerlDuck
9,1931 gold badge18 silver badges44 bronze badges
9,1931 gold badge18 silver badges44 bronze badges
answered Jul 26 at 8:57
ColinBColinB
3182 silver badges7 bronze badges
3182 silver badges7 bronze badges
2
You can change the behaviour as follows:shopt -s nullglobwill yield empty strings for unmatched patterns andshopt -u nullglob(standard setting) will yield the pattern itself.
– PerlDuck
Jul 26 at 9:03
add a comment |
2
You can change the behaviour as follows:shopt -s nullglobwill yield empty strings for unmatched patterns andshopt -u nullglob(standard setting) will yield the pattern itself.
– PerlDuck
Jul 26 at 9:03
2
2
You can change the behaviour as follows:
shopt -s nullglob will yield empty strings for unmatched patterns and shopt -u nullglob (standard setting) will yield the pattern itself.– PerlDuck
Jul 26 at 9:03
You can change the behaviour as follows:
shopt -s nullglob will yield empty strings for unmatched patterns and shopt -u nullglob (standard setting) will yield the pattern itself.– PerlDuck
Jul 26 at 9:03
add a comment |
I was expecting to not get any output.
If nullglob were the default, many commands would behave quite unexpectedly, because it is (perhaps unfortunately) common that commands treat the case of zero filename arguments in a qualitatively different way than the case of one or more filename arguments.
Suppose you've enabled nullglob (shopt -s nullglob) and you're in a directory where no files match *.txt. Then *.txt will indeed expand to nothing--not an empty field, but no fields at all--as you expected. But that would have these results:
ls *.txtwould list all the files in the current directory (except hidden files), because that's whatlsdoes when you don't pass it any filename arguments.cat *.txtwould read from standard input, because whencathas no filename arguments, it's as if you rancat -. If running interactively, it sits around waiting for input. Many commands behave this way.cp *.txt dest/would fail with the errorcp: missing destination file operand after 'dest/'. This isn't a disaster, but it's confusing and quite different from the silent success that is probably desired.file *.txt, and various other programs with no special behavior for the case of zero filename arguments, would still fail with an error or usage message when none are passed.- Even cases that intuitively feel like they should work often wouldn't.
printf 'Got file: "%s"n' *.txtwould printGot file: ""instead of nothing. - Accidental failure to quote occurrences of
*,?, and[that aren't intended to be expanded by the shell would more often produce obviously wrong results, but in ways that might be difficult to figure out. For example, if no filenames in the current directory started withgedit, thenapt list gedit*(whereapt list 'gedit*'was intended) would become justapt listand list all available packages.
So it's good that you don't get this behavior without requesting it. Probably the most common practical situation that is actually simplified by nullglob is for f in *.txt. See also this question (which Sergiy Kolodyazhnyy's answer linked to).
The harder question to answer is why failglob--where it's an expansion error to have a glob that doesn't match any files--isn't the default in bash. I believe Sergiy Kolodyazhnyy's answer captures the reason for this even without addressing it directly. Retaining unexpanding globs without producing an expansion error is (perhaps unfortunately) the standardized behavior, and it is also traditional, and thus expected, behavior. Although bash doesn't attempt to be fully POSIX-compliant unless it is invoked with the name sh or passed the --posix option, many of its design choices even when not in POSIX mode follow POSIX directly. They had to pick some behavior, and there are downsides associated with going against users' expectations.
I think this is the least historically influential aspect of the matter so I've saved it for last... but it is worth mentioning that there's something a bit conceptually odd about nullglob behavior.
nullglob seems elegant at first because, syntactically, it treats the case of zero matching files no differently from the case of one, two, or any other number. The commands we run, which globs expand into arguments for, don't tend to treat them the same, as detailed above. But syntactically this at least feels right, which I think is the motivation for your question.
And yet, there is another, more subtle inconsistency that nullglob doesn't address--that it actually amplifies. The case of zero globbing characters ("wildcards") is treated profoundly differently from that of one, or two, or any other number. For example, with shopt -s nullglob, if ab?d?f doesn't match any files, it is removed; if ab?d doesn't match any files, it is removed; but if ab doesn't match any files (i.e., if there is no file whose name is exactly ab) it is still not removed. Of course, it would be a disaster if it were removed, because it might not be intended to refer to an existing file in the current directory at all; it might not even refer to a file. But this still eliminates any hope for total consistency.
The three behaviors bash provides--the default of treating globs that don't match any files as though they weren't globs and passing them unexpanded, the behavior you expected of treating them (if you'll pardon this odd turn of phrase) as signifying all zero of the files that do match (nullglob), and the safe behavior of considering them errors (failglob)--all represent different approaches to the ambiguity inherent in the shell not being able to know if any particular word is intended to be a filename. The shell performs its expansions without knowledge of how the particular commands you call with it will treat their arguments.
This is one of many instances of separation of concerns. In systems whose design follows the Unix philosophy, each part is intended to do one thing and do it well. The shell processes text into commands and arguments and invokes those commands, most of which are external to the shell itself. This tends to be a lot nicer and more versatile than systems where the external commands are themselves responsible for performing those transformations (as with the traditional command processors in DOS and Windows). But it has its occasional downsides.
Apparently, bash-4.3.39(2) doesn't havefailglob. So it can't the default because it hasn't always been supported.
– Ruslan
Jul 28 at 6:48
add a comment |
I was expecting to not get any output.
If nullglob were the default, many commands would behave quite unexpectedly, because it is (perhaps unfortunately) common that commands treat the case of zero filename arguments in a qualitatively different way than the case of one or more filename arguments.
Suppose you've enabled nullglob (shopt -s nullglob) and you're in a directory where no files match *.txt. Then *.txt will indeed expand to nothing--not an empty field, but no fields at all--as you expected. But that would have these results:
ls *.txtwould list all the files in the current directory (except hidden files), because that's whatlsdoes when you don't pass it any filename arguments.cat *.txtwould read from standard input, because whencathas no filename arguments, it's as if you rancat -. If running interactively, it sits around waiting for input. Many commands behave this way.cp *.txt dest/would fail with the errorcp: missing destination file operand after 'dest/'. This isn't a disaster, but it's confusing and quite different from the silent success that is probably desired.file *.txt, and various other programs with no special behavior for the case of zero filename arguments, would still fail with an error or usage message when none are passed.- Even cases that intuitively feel like they should work often wouldn't.
printf 'Got file: "%s"n' *.txtwould printGot file: ""instead of nothing. - Accidental failure to quote occurrences of
*,?, and[that aren't intended to be expanded by the shell would more often produce obviously wrong results, but in ways that might be difficult to figure out. For example, if no filenames in the current directory started withgedit, thenapt list gedit*(whereapt list 'gedit*'was intended) would become justapt listand list all available packages.
So it's good that you don't get this behavior without requesting it. Probably the most common practical situation that is actually simplified by nullglob is for f in *.txt. See also this question (which Sergiy Kolodyazhnyy's answer linked to).
The harder question to answer is why failglob--where it's an expansion error to have a glob that doesn't match any files--isn't the default in bash. I believe Sergiy Kolodyazhnyy's answer captures the reason for this even without addressing it directly. Retaining unexpanding globs without producing an expansion error is (perhaps unfortunately) the standardized behavior, and it is also traditional, and thus expected, behavior. Although bash doesn't attempt to be fully POSIX-compliant unless it is invoked with the name sh or passed the --posix option, many of its design choices even when not in POSIX mode follow POSIX directly. They had to pick some behavior, and there are downsides associated with going against users' expectations.
I think this is the least historically influential aspect of the matter so I've saved it for last... but it is worth mentioning that there's something a bit conceptually odd about nullglob behavior.
nullglob seems elegant at first because, syntactically, it treats the case of zero matching files no differently from the case of one, two, or any other number. The commands we run, which globs expand into arguments for, don't tend to treat them the same, as detailed above. But syntactically this at least feels right, which I think is the motivation for your question.
And yet, there is another, more subtle inconsistency that nullglob doesn't address--that it actually amplifies. The case of zero globbing characters ("wildcards") is treated profoundly differently from that of one, or two, or any other number. For example, with shopt -s nullglob, if ab?d?f doesn't match any files, it is removed; if ab?d doesn't match any files, it is removed; but if ab doesn't match any files (i.e., if there is no file whose name is exactly ab) it is still not removed. Of course, it would be a disaster if it were removed, because it might not be intended to refer to an existing file in the current directory at all; it might not even refer to a file. But this still eliminates any hope for total consistency.
The three behaviors bash provides--the default of treating globs that don't match any files as though they weren't globs and passing them unexpanded, the behavior you expected of treating them (if you'll pardon this odd turn of phrase) as signifying all zero of the files that do match (nullglob), and the safe behavior of considering them errors (failglob)--all represent different approaches to the ambiguity inherent in the shell not being able to know if any particular word is intended to be a filename. The shell performs its expansions without knowledge of how the particular commands you call with it will treat their arguments.
This is one of many instances of separation of concerns. In systems whose design follows the Unix philosophy, each part is intended to do one thing and do it well. The shell processes text into commands and arguments and invokes those commands, most of which are external to the shell itself. This tends to be a lot nicer and more versatile than systems where the external commands are themselves responsible for performing those transformations (as with the traditional command processors in DOS and Windows). But it has its occasional downsides.
Apparently, bash-4.3.39(2) doesn't havefailglob. So it can't the default because it hasn't always been supported.
– Ruslan
Jul 28 at 6:48
add a comment |
I was expecting to not get any output.
If nullglob were the default, many commands would behave quite unexpectedly, because it is (perhaps unfortunately) common that commands treat the case of zero filename arguments in a qualitatively different way than the case of one or more filename arguments.
Suppose you've enabled nullglob (shopt -s nullglob) and you're in a directory where no files match *.txt. Then *.txt will indeed expand to nothing--not an empty field, but no fields at all--as you expected. But that would have these results:
ls *.txtwould list all the files in the current directory (except hidden files), because that's whatlsdoes when you don't pass it any filename arguments.cat *.txtwould read from standard input, because whencathas no filename arguments, it's as if you rancat -. If running interactively, it sits around waiting for input. Many commands behave this way.cp *.txt dest/would fail with the errorcp: missing destination file operand after 'dest/'. This isn't a disaster, but it's confusing and quite different from the silent success that is probably desired.file *.txt, and various other programs with no special behavior for the case of zero filename arguments, would still fail with an error or usage message when none are passed.- Even cases that intuitively feel like they should work often wouldn't.
printf 'Got file: "%s"n' *.txtwould printGot file: ""instead of nothing. - Accidental failure to quote occurrences of
*,?, and[that aren't intended to be expanded by the shell would more often produce obviously wrong results, but in ways that might be difficult to figure out. For example, if no filenames in the current directory started withgedit, thenapt list gedit*(whereapt list 'gedit*'was intended) would become justapt listand list all available packages.
So it's good that you don't get this behavior without requesting it. Probably the most common practical situation that is actually simplified by nullglob is for f in *.txt. See also this question (which Sergiy Kolodyazhnyy's answer linked to).
The harder question to answer is why failglob--where it's an expansion error to have a glob that doesn't match any files--isn't the default in bash. I believe Sergiy Kolodyazhnyy's answer captures the reason for this even without addressing it directly. Retaining unexpanding globs without producing an expansion error is (perhaps unfortunately) the standardized behavior, and it is also traditional, and thus expected, behavior. Although bash doesn't attempt to be fully POSIX-compliant unless it is invoked with the name sh or passed the --posix option, many of its design choices even when not in POSIX mode follow POSIX directly. They had to pick some behavior, and there are downsides associated with going against users' expectations.
I think this is the least historically influential aspect of the matter so I've saved it for last... but it is worth mentioning that there's something a bit conceptually odd about nullglob behavior.
nullglob seems elegant at first because, syntactically, it treats the case of zero matching files no differently from the case of one, two, or any other number. The commands we run, which globs expand into arguments for, don't tend to treat them the same, as detailed above. But syntactically this at least feels right, which I think is the motivation for your question.
And yet, there is another, more subtle inconsistency that nullglob doesn't address--that it actually amplifies. The case of zero globbing characters ("wildcards") is treated profoundly differently from that of one, or two, or any other number. For example, with shopt -s nullglob, if ab?d?f doesn't match any files, it is removed; if ab?d doesn't match any files, it is removed; but if ab doesn't match any files (i.e., if there is no file whose name is exactly ab) it is still not removed. Of course, it would be a disaster if it were removed, because it might not be intended to refer to an existing file in the current directory at all; it might not even refer to a file. But this still eliminates any hope for total consistency.
The three behaviors bash provides--the default of treating globs that don't match any files as though they weren't globs and passing them unexpanded, the behavior you expected of treating them (if you'll pardon this odd turn of phrase) as signifying all zero of the files that do match (nullglob), and the safe behavior of considering them errors (failglob)--all represent different approaches to the ambiguity inherent in the shell not being able to know if any particular word is intended to be a filename. The shell performs its expansions without knowledge of how the particular commands you call with it will treat their arguments.
This is one of many instances of separation of concerns. In systems whose design follows the Unix philosophy, each part is intended to do one thing and do it well. The shell processes text into commands and arguments and invokes those commands, most of which are external to the shell itself. This tends to be a lot nicer and more versatile than systems where the external commands are themselves responsible for performing those transformations (as with the traditional command processors in DOS and Windows). But it has its occasional downsides.
I was expecting to not get any output.
If nullglob were the default, many commands would behave quite unexpectedly, because it is (perhaps unfortunately) common that commands treat the case of zero filename arguments in a qualitatively different way than the case of one or more filename arguments.
Suppose you've enabled nullglob (shopt -s nullglob) and you're in a directory where no files match *.txt. Then *.txt will indeed expand to nothing--not an empty field, but no fields at all--as you expected. But that would have these results:
ls *.txtwould list all the files in the current directory (except hidden files), because that's whatlsdoes when you don't pass it any filename arguments.cat *.txtwould read from standard input, because whencathas no filename arguments, it's as if you rancat -. If running interactively, it sits around waiting for input. Many commands behave this way.cp *.txt dest/would fail with the errorcp: missing destination file operand after 'dest/'. This isn't a disaster, but it's confusing and quite different from the silent success that is probably desired.file *.txt, and various other programs with no special behavior for the case of zero filename arguments, would still fail with an error or usage message when none are passed.- Even cases that intuitively feel like they should work often wouldn't.
printf 'Got file: "%s"n' *.txtwould printGot file: ""instead of nothing. - Accidental failure to quote occurrences of
*,?, and[that aren't intended to be expanded by the shell would more often produce obviously wrong results, but in ways that might be difficult to figure out. For example, if no filenames in the current directory started withgedit, thenapt list gedit*(whereapt list 'gedit*'was intended) would become justapt listand list all available packages.
So it's good that you don't get this behavior without requesting it. Probably the most common practical situation that is actually simplified by nullglob is for f in *.txt. See also this question (which Sergiy Kolodyazhnyy's answer linked to).
The harder question to answer is why failglob--where it's an expansion error to have a glob that doesn't match any files--isn't the default in bash. I believe Sergiy Kolodyazhnyy's answer captures the reason for this even without addressing it directly. Retaining unexpanding globs without producing an expansion error is (perhaps unfortunately) the standardized behavior, and it is also traditional, and thus expected, behavior. Although bash doesn't attempt to be fully POSIX-compliant unless it is invoked with the name sh or passed the --posix option, many of its design choices even when not in POSIX mode follow POSIX directly. They had to pick some behavior, and there are downsides associated with going against users' expectations.
I think this is the least historically influential aspect of the matter so I've saved it for last... but it is worth mentioning that there's something a bit conceptually odd about nullglob behavior.
nullglob seems elegant at first because, syntactically, it treats the case of zero matching files no differently from the case of one, two, or any other number. The commands we run, which globs expand into arguments for, don't tend to treat them the same, as detailed above. But syntactically this at least feels right, which I think is the motivation for your question.
And yet, there is another, more subtle inconsistency that nullglob doesn't address--that it actually amplifies. The case of zero globbing characters ("wildcards") is treated profoundly differently from that of one, or two, or any other number. For example, with shopt -s nullglob, if ab?d?f doesn't match any files, it is removed; if ab?d doesn't match any files, it is removed; but if ab doesn't match any files (i.e., if there is no file whose name is exactly ab) it is still not removed. Of course, it would be a disaster if it were removed, because it might not be intended to refer to an existing file in the current directory at all; it might not even refer to a file. But this still eliminates any hope for total consistency.
The three behaviors bash provides--the default of treating globs that don't match any files as though they weren't globs and passing them unexpanded, the behavior you expected of treating them (if you'll pardon this odd turn of phrase) as signifying all zero of the files that do match (nullglob), and the safe behavior of considering them errors (failglob)--all represent different approaches to the ambiguity inherent in the shell not being able to know if any particular word is intended to be a filename. The shell performs its expansions without knowledge of how the particular commands you call with it will treat their arguments.
This is one of many instances of separation of concerns. In systems whose design follows the Unix philosophy, each part is intended to do one thing and do it well. The shell processes text into commands and arguments and invokes those commands, most of which are external to the shell itself. This tends to be a lot nicer and more versatile than systems where the external commands are themselves responsible for performing those transformations (as with the traditional command processors in DOS and Windows). But it has its occasional downsides.
edited Jul 27 at 23:45
answered Jul 26 at 19:43
Eliah KaganEliah Kagan
87.7k22 gold badges243 silver badges386 bronze badges
87.7k22 gold badges243 silver badges386 bronze badges
Apparently, bash-4.3.39(2) doesn't havefailglob. So it can't the default because it hasn't always been supported.
– Ruslan
Jul 28 at 6:48
add a comment |
Apparently, bash-4.3.39(2) doesn't havefailglob. So it can't the default because it hasn't always been supported.
– Ruslan
Jul 28 at 6:48
Apparently, bash-4.3.39(2) doesn't have
failglob. So it can't the default because it hasn't always been supported.– Ruslan
Jul 28 at 6:48
Apparently, bash-4.3.39(2) doesn't have
failglob. So it can't the default because it hasn't always been supported.– Ruslan
Jul 28 at 6:48
add a comment |
The main reason is because this is standard behavior specified by POSIX - the standard which covers shell command language and among other things pattern matching ( shells such as bash, dash shell - Ubuntu's default /bin/sh, and ksh follow this standard ). From section 2.13.3 Patterns Used for Filename Expansion:
If the pattern does not match any existing filenames or pathnames, the pattern string shall be left unchanged.
This of course has a side effect - matching filename that may be literally *.txt. The nullglob option in bash and zsh can help: if that option is enabled via shopt -s nullglob (and it is not enabled by default which applies to this question), then globstar will be expanded to empty string when no matching filenames found. ksh93 has its own advanced pattern matching mechanism which achieves the same effect ~(N)*.txt
See also Why is nullglob not default?
add a comment |
The main reason is because this is standard behavior specified by POSIX - the standard which covers shell command language and among other things pattern matching ( shells such as bash, dash shell - Ubuntu's default /bin/sh, and ksh follow this standard ). From section 2.13.3 Patterns Used for Filename Expansion:
If the pattern does not match any existing filenames or pathnames, the pattern string shall be left unchanged.
This of course has a side effect - matching filename that may be literally *.txt. The nullglob option in bash and zsh can help: if that option is enabled via shopt -s nullglob (and it is not enabled by default which applies to this question), then globstar will be expanded to empty string when no matching filenames found. ksh93 has its own advanced pattern matching mechanism which achieves the same effect ~(N)*.txt
See also Why is nullglob not default?
add a comment |
The main reason is because this is standard behavior specified by POSIX - the standard which covers shell command language and among other things pattern matching ( shells such as bash, dash shell - Ubuntu's default /bin/sh, and ksh follow this standard ). From section 2.13.3 Patterns Used for Filename Expansion:
If the pattern does not match any existing filenames or pathnames, the pattern string shall be left unchanged.
This of course has a side effect - matching filename that may be literally *.txt. The nullglob option in bash and zsh can help: if that option is enabled via shopt -s nullglob (and it is not enabled by default which applies to this question), then globstar will be expanded to empty string when no matching filenames found. ksh93 has its own advanced pattern matching mechanism which achieves the same effect ~(N)*.txt
See also Why is nullglob not default?
The main reason is because this is standard behavior specified by POSIX - the standard which covers shell command language and among other things pattern matching ( shells such as bash, dash shell - Ubuntu's default /bin/sh, and ksh follow this standard ). From section 2.13.3 Patterns Used for Filename Expansion:
If the pattern does not match any existing filenames or pathnames, the pattern string shall be left unchanged.
This of course has a side effect - matching filename that may be literally *.txt. The nullglob option in bash and zsh can help: if that option is enabled via shopt -s nullglob (and it is not enabled by default which applies to this question), then globstar will be expanded to empty string when no matching filenames found. ksh93 has its own advanced pattern matching mechanism which achieves the same effect ~(N)*.txt
See also Why is nullglob not default?
edited Jul 26 at 18:45
answered Jul 26 at 9:04
Sergiy KolodyazhnyySergiy Kolodyazhnyy
78.4k11 gold badges168 silver badges346 bronze badges
78.4k11 gold badges168 silver badges346 bronze badges
add a comment |
add a comment |
Thanks for contributing an answer to Ask Ubuntu!
- 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%2faskubuntu.com%2fquestions%2f1161180%2fexpansion-with-txt-in-the-shell-doesnt-work-if-no-txt-file-exists%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