Can you explain these three things in this bash code for me?
I have a function
in my .bashrc
file. I know what it does, it steps up X many directories with cd
Here it is:
up()
{
local d=""
limit=$1
for ((i=1 ; i <= limit ; i++))
do
d=$d/..
done
d=$(echo $d | sed 's/^///')
if [ -z "$d" ]; then
d=..
fi
cd $d
}
But can you explain these three things from it for me?
d=$d/..
sed 's/^///'
d=..
Why not just do like this:
up()
{
limit=$1
for ((i=1 ; i <= limit ; i++))
do
cd ..
done
}
Usage:
<<<>>>~$ up 3
<<<>>>/$
shell sed variable function cd-command
add a comment |
I have a function
in my .bashrc
file. I know what it does, it steps up X many directories with cd
Here it is:
up()
{
local d=""
limit=$1
for ((i=1 ; i <= limit ; i++))
do
d=$d/..
done
d=$(echo $d | sed 's/^///')
if [ -z "$d" ]; then
d=..
fi
cd $d
}
But can you explain these three things from it for me?
d=$d/..
sed 's/^///'
d=..
Why not just do like this:
up()
{
limit=$1
for ((i=1 ; i <= limit ; i++))
do
cd ..
done
}
Usage:
<<<>>>~$ up 3
<<<>>>/$
shell sed variable function cd-command
add a comment |
I have a function
in my .bashrc
file. I know what it does, it steps up X many directories with cd
Here it is:
up()
{
local d=""
limit=$1
for ((i=1 ; i <= limit ; i++))
do
d=$d/..
done
d=$(echo $d | sed 's/^///')
if [ -z "$d" ]; then
d=..
fi
cd $d
}
But can you explain these three things from it for me?
d=$d/..
sed 's/^///'
d=..
Why not just do like this:
up()
{
limit=$1
for ((i=1 ; i <= limit ; i++))
do
cd ..
done
}
Usage:
<<<>>>~$ up 3
<<<>>>/$
shell sed variable function cd-command
I have a function
in my .bashrc
file. I know what it does, it steps up X many directories with cd
Here it is:
up()
{
local d=""
limit=$1
for ((i=1 ; i <= limit ; i++))
do
d=$d/..
done
d=$(echo $d | sed 's/^///')
if [ -z "$d" ]; then
d=..
fi
cd $d
}
But can you explain these three things from it for me?
d=$d/..
sed 's/^///'
d=..
Why not just do like this:
up()
{
limit=$1
for ((i=1 ; i <= limit ; i++))
do
cd ..
done
}
Usage:
<<<>>>~$ up 3
<<<>>>/$
shell sed variable function cd-command
shell sed variable function cd-command
edited 10 hours ago
Rui F Ribeiro
41.3k1481140
41.3k1481140
asked Oct 18 '18 at 9:34
somethingSomethingsomethingSomething
1,792103259
1,792103259
add a comment |
add a comment |
2 Answers
2
active
oldest
votes
d=$d/..
adds/..
to the current contents of thed
variable.d
starts off empty, then the first iteration makes it/..
, the second/../..
etc.sed 's/^///'
drops the first/
, so/../..
becomes../..
(this can be done using a parameter expansion,d=${d#/}
).
d=..
only makes sense in the context of its condition:
if [ -z "$d" ]; then
d=..
fi
This ensures that, if
d
is empty at this point, you go to the parent directory. (up
with no argument is equivalent tocd ..
.)
This approach is better than iterative cd ..
because it preserves cd -
— the ability to return to the previous directory (from the user’s perspective) in one step.
The function can be simplified:
up() {
local d=..
for ((i = 1; i < ${1:-1}; i++)); do d=$d/..; done
cd $d
}
This assumes we want to move up at least one level, and adds n - 1 levels, so we don’t need to remove the leading /
or check for an empty $d
.
Using Athena jot
(the athena-jot
package in Debian):
up() { cd $(jot -b .. -s / "${1:-1}"); }
(based on a variant suggested by glenn jackman).
Yep,$OLDPWD
getting trampled on came to mind. And on zsh withcd
set to use the dirstack, that too.
– muru
Oct 18 '18 at 10:08
Is there some reason for assigning$1
tolimit
instead of just using$1
in the loop?
– kundor
Oct 18 '18 at 16:24
1
@kundor it ensures the default is 0 (see shell arithmetic). We could use${1:-1}
instead, as in glenn’s variant.
– Stephen Kitt
Oct 18 '18 at 16:37
@kundor Also human readability. A well-named variable tells you what the intended meaning or purpose of the first argument is when you start reading the function, without having to first know what the function does or finish understanding the code to deduce it.
– mtraceur
Oct 18 '18 at 20:43
add a comment |
But can you explain these three things from it for me?
d=$d/..
This concatenates the present contents of var
d
with/..
and assign it back tod
.
The end result is to maked
a repeated string like/../../../..
.
sed 's/^///'
Remove the leading
/
from the string supplied,d
(echo $d) in the code you posted.
Probably better written assed 's|^/||'
to avoid the backslash.
An alternative (faster and simpler) is to write
d=${d#/}
.
d=..
Assign the string
..
to the vard
.
This only makes sense as a way to ensure thatd
has at least one..
in case the testif [ -z "$d" ]; then
signals that the vard
is empty.
And that can only happen because the sed command is removing one character fromd
.
If there is no need to remove the character from d, there is no need forsed
orif
.
The code in your question will always move up at least one dir.
Better
local d
is enough to make sure that the variable is empty, nothing else is needed.
However, local works only in some shells like bash or dash. In specific,ksh
(asyash
) doesn't have alocal
command. A more portable solution is:
[ "$KSH_VERSION$YASH_VERSION" ] && typeset c='' d='' i='' || local c='' d='' i=''
The
for((
syntax is not portable. Better use something like:
while [ "$((i+=1))" -lt "$limit" ]; do
Robust.
If the values given to the function first argument could be negative or text, the function should be robust to process those values.
First, lets limit the values to only numbers (I'll usec
forcount
):
c=${1%%[!0-9]*}
And then limit the count value only to positive values:
let "c = (c>0)?c:0"
This function will hapily accept 0 or any text (without errors):
up()
{
[ "$KSH_VERSION$YASH_VERSION" ] && typeset c='' d='' i='' || local c='' d='' i=''
c=${1%%[!0-9]*}
c=$(((c>0)?c:0))
while [ "$((i+=1))" -le "$c" ]; do d="$d../"; done
echo
cd "${d%/}" # Removing the trailing / is not really needed for cd
# but it is nice to know it could be done cleanly.
}
up 2
up 0
up asdf
Remove the echo
when you have tested the function.
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%2f476253%2fcan-you-explain-these-three-things-in-this-bash-code-for-me%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
d=$d/..
adds/..
to the current contents of thed
variable.d
starts off empty, then the first iteration makes it/..
, the second/../..
etc.sed 's/^///'
drops the first/
, so/../..
becomes../..
(this can be done using a parameter expansion,d=${d#/}
).
d=..
only makes sense in the context of its condition:
if [ -z "$d" ]; then
d=..
fi
This ensures that, if
d
is empty at this point, you go to the parent directory. (up
with no argument is equivalent tocd ..
.)
This approach is better than iterative cd ..
because it preserves cd -
— the ability to return to the previous directory (from the user’s perspective) in one step.
The function can be simplified:
up() {
local d=..
for ((i = 1; i < ${1:-1}; i++)); do d=$d/..; done
cd $d
}
This assumes we want to move up at least one level, and adds n - 1 levels, so we don’t need to remove the leading /
or check for an empty $d
.
Using Athena jot
(the athena-jot
package in Debian):
up() { cd $(jot -b .. -s / "${1:-1}"); }
(based on a variant suggested by glenn jackman).
Yep,$OLDPWD
getting trampled on came to mind. And on zsh withcd
set to use the dirstack, that too.
– muru
Oct 18 '18 at 10:08
Is there some reason for assigning$1
tolimit
instead of just using$1
in the loop?
– kundor
Oct 18 '18 at 16:24
1
@kundor it ensures the default is 0 (see shell arithmetic). We could use${1:-1}
instead, as in glenn’s variant.
– Stephen Kitt
Oct 18 '18 at 16:37
@kundor Also human readability. A well-named variable tells you what the intended meaning or purpose of the first argument is when you start reading the function, without having to first know what the function does or finish understanding the code to deduce it.
– mtraceur
Oct 18 '18 at 20:43
add a comment |
d=$d/..
adds/..
to the current contents of thed
variable.d
starts off empty, then the first iteration makes it/..
, the second/../..
etc.sed 's/^///'
drops the first/
, so/../..
becomes../..
(this can be done using a parameter expansion,d=${d#/}
).
d=..
only makes sense in the context of its condition:
if [ -z "$d" ]; then
d=..
fi
This ensures that, if
d
is empty at this point, you go to the parent directory. (up
with no argument is equivalent tocd ..
.)
This approach is better than iterative cd ..
because it preserves cd -
— the ability to return to the previous directory (from the user’s perspective) in one step.
The function can be simplified:
up() {
local d=..
for ((i = 1; i < ${1:-1}; i++)); do d=$d/..; done
cd $d
}
This assumes we want to move up at least one level, and adds n - 1 levels, so we don’t need to remove the leading /
or check for an empty $d
.
Using Athena jot
(the athena-jot
package in Debian):
up() { cd $(jot -b .. -s / "${1:-1}"); }
(based on a variant suggested by glenn jackman).
Yep,$OLDPWD
getting trampled on came to mind. And on zsh withcd
set to use the dirstack, that too.
– muru
Oct 18 '18 at 10:08
Is there some reason for assigning$1
tolimit
instead of just using$1
in the loop?
– kundor
Oct 18 '18 at 16:24
1
@kundor it ensures the default is 0 (see shell arithmetic). We could use${1:-1}
instead, as in glenn’s variant.
– Stephen Kitt
Oct 18 '18 at 16:37
@kundor Also human readability. A well-named variable tells you what the intended meaning or purpose of the first argument is when you start reading the function, without having to first know what the function does or finish understanding the code to deduce it.
– mtraceur
Oct 18 '18 at 20:43
add a comment |
d=$d/..
adds/..
to the current contents of thed
variable.d
starts off empty, then the first iteration makes it/..
, the second/../..
etc.sed 's/^///'
drops the first/
, so/../..
becomes../..
(this can be done using a parameter expansion,d=${d#/}
).
d=..
only makes sense in the context of its condition:
if [ -z "$d" ]; then
d=..
fi
This ensures that, if
d
is empty at this point, you go to the parent directory. (up
with no argument is equivalent tocd ..
.)
This approach is better than iterative cd ..
because it preserves cd -
— the ability to return to the previous directory (from the user’s perspective) in one step.
The function can be simplified:
up() {
local d=..
for ((i = 1; i < ${1:-1}; i++)); do d=$d/..; done
cd $d
}
This assumes we want to move up at least one level, and adds n - 1 levels, so we don’t need to remove the leading /
or check for an empty $d
.
Using Athena jot
(the athena-jot
package in Debian):
up() { cd $(jot -b .. -s / "${1:-1}"); }
(based on a variant suggested by glenn jackman).
d=$d/..
adds/..
to the current contents of thed
variable.d
starts off empty, then the first iteration makes it/..
, the second/../..
etc.sed 's/^///'
drops the first/
, so/../..
becomes../..
(this can be done using a parameter expansion,d=${d#/}
).
d=..
only makes sense in the context of its condition:
if [ -z "$d" ]; then
d=..
fi
This ensures that, if
d
is empty at this point, you go to the parent directory. (up
with no argument is equivalent tocd ..
.)
This approach is better than iterative cd ..
because it preserves cd -
— the ability to return to the previous directory (from the user’s perspective) in one step.
The function can be simplified:
up() {
local d=..
for ((i = 1; i < ${1:-1}; i++)); do d=$d/..; done
cd $d
}
This assumes we want to move up at least one level, and adds n - 1 levels, so we don’t need to remove the leading /
or check for an empty $d
.
Using Athena jot
(the athena-jot
package in Debian):
up() { cd $(jot -b .. -s / "${1:-1}"); }
(based on a variant suggested by glenn jackman).
edited Oct 18 '18 at 16:41
answered Oct 18 '18 at 10:05
Stephen KittStephen Kitt
175k24400477
175k24400477
Yep,$OLDPWD
getting trampled on came to mind. And on zsh withcd
set to use the dirstack, that too.
– muru
Oct 18 '18 at 10:08
Is there some reason for assigning$1
tolimit
instead of just using$1
in the loop?
– kundor
Oct 18 '18 at 16:24
1
@kundor it ensures the default is 0 (see shell arithmetic). We could use${1:-1}
instead, as in glenn’s variant.
– Stephen Kitt
Oct 18 '18 at 16:37
@kundor Also human readability. A well-named variable tells you what the intended meaning or purpose of the first argument is when you start reading the function, without having to first know what the function does or finish understanding the code to deduce it.
– mtraceur
Oct 18 '18 at 20:43
add a comment |
Yep,$OLDPWD
getting trampled on came to mind. And on zsh withcd
set to use the dirstack, that too.
– muru
Oct 18 '18 at 10:08
Is there some reason for assigning$1
tolimit
instead of just using$1
in the loop?
– kundor
Oct 18 '18 at 16:24
1
@kundor it ensures the default is 0 (see shell arithmetic). We could use${1:-1}
instead, as in glenn’s variant.
– Stephen Kitt
Oct 18 '18 at 16:37
@kundor Also human readability. A well-named variable tells you what the intended meaning or purpose of the first argument is when you start reading the function, without having to first know what the function does or finish understanding the code to deduce it.
– mtraceur
Oct 18 '18 at 20:43
Yep,
$OLDPWD
getting trampled on came to mind. And on zsh with cd
set to use the dirstack, that too.– muru
Oct 18 '18 at 10:08
Yep,
$OLDPWD
getting trampled on came to mind. And on zsh with cd
set to use the dirstack, that too.– muru
Oct 18 '18 at 10:08
Is there some reason for assigning
$1
to limit
instead of just using $1
in the loop?– kundor
Oct 18 '18 at 16:24
Is there some reason for assigning
$1
to limit
instead of just using $1
in the loop?– kundor
Oct 18 '18 at 16:24
1
1
@kundor it ensures the default is 0 (see shell arithmetic). We could use
${1:-1}
instead, as in glenn’s variant.– Stephen Kitt
Oct 18 '18 at 16:37
@kundor it ensures the default is 0 (see shell arithmetic). We could use
${1:-1}
instead, as in glenn’s variant.– Stephen Kitt
Oct 18 '18 at 16:37
@kundor Also human readability. A well-named variable tells you what the intended meaning or purpose of the first argument is when you start reading the function, without having to first know what the function does or finish understanding the code to deduce it.
– mtraceur
Oct 18 '18 at 20:43
@kundor Also human readability. A well-named variable tells you what the intended meaning or purpose of the first argument is when you start reading the function, without having to first know what the function does or finish understanding the code to deduce it.
– mtraceur
Oct 18 '18 at 20:43
add a comment |
But can you explain these three things from it for me?
d=$d/..
This concatenates the present contents of var
d
with/..
and assign it back tod
.
The end result is to maked
a repeated string like/../../../..
.
sed 's/^///'
Remove the leading
/
from the string supplied,d
(echo $d) in the code you posted.
Probably better written assed 's|^/||'
to avoid the backslash.
An alternative (faster and simpler) is to write
d=${d#/}
.
d=..
Assign the string
..
to the vard
.
This only makes sense as a way to ensure thatd
has at least one..
in case the testif [ -z "$d" ]; then
signals that the vard
is empty.
And that can only happen because the sed command is removing one character fromd
.
If there is no need to remove the character from d, there is no need forsed
orif
.
The code in your question will always move up at least one dir.
Better
local d
is enough to make sure that the variable is empty, nothing else is needed.
However, local works only in some shells like bash or dash. In specific,ksh
(asyash
) doesn't have alocal
command. A more portable solution is:
[ "$KSH_VERSION$YASH_VERSION" ] && typeset c='' d='' i='' || local c='' d='' i=''
The
for((
syntax is not portable. Better use something like:
while [ "$((i+=1))" -lt "$limit" ]; do
Robust.
If the values given to the function first argument could be negative or text, the function should be robust to process those values.
First, lets limit the values to only numbers (I'll usec
forcount
):
c=${1%%[!0-9]*}
And then limit the count value only to positive values:
let "c = (c>0)?c:0"
This function will hapily accept 0 or any text (without errors):
up()
{
[ "$KSH_VERSION$YASH_VERSION" ] && typeset c='' d='' i='' || local c='' d='' i=''
c=${1%%[!0-9]*}
c=$(((c>0)?c:0))
while [ "$((i+=1))" -le "$c" ]; do d="$d../"; done
echo
cd "${d%/}" # Removing the trailing / is not really needed for cd
# but it is nice to know it could be done cleanly.
}
up 2
up 0
up asdf
Remove the echo
when you have tested the function.
add a comment |
But can you explain these three things from it for me?
d=$d/..
This concatenates the present contents of var
d
with/..
and assign it back tod
.
The end result is to maked
a repeated string like/../../../..
.
sed 's/^///'
Remove the leading
/
from the string supplied,d
(echo $d) in the code you posted.
Probably better written assed 's|^/||'
to avoid the backslash.
An alternative (faster and simpler) is to write
d=${d#/}
.
d=..
Assign the string
..
to the vard
.
This only makes sense as a way to ensure thatd
has at least one..
in case the testif [ -z "$d" ]; then
signals that the vard
is empty.
And that can only happen because the sed command is removing one character fromd
.
If there is no need to remove the character from d, there is no need forsed
orif
.
The code in your question will always move up at least one dir.
Better
local d
is enough to make sure that the variable is empty, nothing else is needed.
However, local works only in some shells like bash or dash. In specific,ksh
(asyash
) doesn't have alocal
command. A more portable solution is:
[ "$KSH_VERSION$YASH_VERSION" ] && typeset c='' d='' i='' || local c='' d='' i=''
The
for((
syntax is not portable. Better use something like:
while [ "$((i+=1))" -lt "$limit" ]; do
Robust.
If the values given to the function first argument could be negative or text, the function should be robust to process those values.
First, lets limit the values to only numbers (I'll usec
forcount
):
c=${1%%[!0-9]*}
And then limit the count value only to positive values:
let "c = (c>0)?c:0"
This function will hapily accept 0 or any text (without errors):
up()
{
[ "$KSH_VERSION$YASH_VERSION" ] && typeset c='' d='' i='' || local c='' d='' i=''
c=${1%%[!0-9]*}
c=$(((c>0)?c:0))
while [ "$((i+=1))" -le "$c" ]; do d="$d../"; done
echo
cd "${d%/}" # Removing the trailing / is not really needed for cd
# but it is nice to know it could be done cleanly.
}
up 2
up 0
up asdf
Remove the echo
when you have tested the function.
add a comment |
But can you explain these three things from it for me?
d=$d/..
This concatenates the present contents of var
d
with/..
and assign it back tod
.
The end result is to maked
a repeated string like/../../../..
.
sed 's/^///'
Remove the leading
/
from the string supplied,d
(echo $d) in the code you posted.
Probably better written assed 's|^/||'
to avoid the backslash.
An alternative (faster and simpler) is to write
d=${d#/}
.
d=..
Assign the string
..
to the vard
.
This only makes sense as a way to ensure thatd
has at least one..
in case the testif [ -z "$d" ]; then
signals that the vard
is empty.
And that can only happen because the sed command is removing one character fromd
.
If there is no need to remove the character from d, there is no need forsed
orif
.
The code in your question will always move up at least one dir.
Better
local d
is enough to make sure that the variable is empty, nothing else is needed.
However, local works only in some shells like bash or dash. In specific,ksh
(asyash
) doesn't have alocal
command. A more portable solution is:
[ "$KSH_VERSION$YASH_VERSION" ] && typeset c='' d='' i='' || local c='' d='' i=''
The
for((
syntax is not portable. Better use something like:
while [ "$((i+=1))" -lt "$limit" ]; do
Robust.
If the values given to the function first argument could be negative or text, the function should be robust to process those values.
First, lets limit the values to only numbers (I'll usec
forcount
):
c=${1%%[!0-9]*}
And then limit the count value only to positive values:
let "c = (c>0)?c:0"
This function will hapily accept 0 or any text (without errors):
up()
{
[ "$KSH_VERSION$YASH_VERSION" ] && typeset c='' d='' i='' || local c='' d='' i=''
c=${1%%[!0-9]*}
c=$(((c>0)?c:0))
while [ "$((i+=1))" -le "$c" ]; do d="$d../"; done
echo
cd "${d%/}" # Removing the trailing / is not really needed for cd
# but it is nice to know it could be done cleanly.
}
up 2
up 0
up asdf
Remove the echo
when you have tested the function.
But can you explain these three things from it for me?
d=$d/..
This concatenates the present contents of var
d
with/..
and assign it back tod
.
The end result is to maked
a repeated string like/../../../..
.
sed 's/^///'
Remove the leading
/
from the string supplied,d
(echo $d) in the code you posted.
Probably better written assed 's|^/||'
to avoid the backslash.
An alternative (faster and simpler) is to write
d=${d#/}
.
d=..
Assign the string
..
to the vard
.
This only makes sense as a way to ensure thatd
has at least one..
in case the testif [ -z "$d" ]; then
signals that the vard
is empty.
And that can only happen because the sed command is removing one character fromd
.
If there is no need to remove the character from d, there is no need forsed
orif
.
The code in your question will always move up at least one dir.
Better
local d
is enough to make sure that the variable is empty, nothing else is needed.
However, local works only in some shells like bash or dash. In specific,ksh
(asyash
) doesn't have alocal
command. A more portable solution is:
[ "$KSH_VERSION$YASH_VERSION" ] && typeset c='' d='' i='' || local c='' d='' i=''
The
for((
syntax is not portable. Better use something like:
while [ "$((i+=1))" -lt "$limit" ]; do
Robust.
If the values given to the function first argument could be negative or text, the function should be robust to process those values.
First, lets limit the values to only numbers (I'll usec
forcount
):
c=${1%%[!0-9]*}
And then limit the count value only to positive values:
let "c = (c>0)?c:0"
This function will hapily accept 0 or any text (without errors):
up()
{
[ "$KSH_VERSION$YASH_VERSION" ] && typeset c='' d='' i='' || local c='' d='' i=''
c=${1%%[!0-9]*}
c=$(((c>0)?c:0))
while [ "$((i+=1))" -le "$c" ]; do d="$d../"; done
echo
cd "${d%/}" # Removing the trailing / is not really needed for cd
# but it is nice to know it could be done cleanly.
}
up 2
up 0
up asdf
Remove the echo
when you have tested the function.
edited Oct 18 '18 at 22:54
answered Oct 18 '18 at 22:13
IsaacIsaac
12k11852
12k11852
add a comment |
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%2f476253%2fcan-you-explain-these-three-things-in-this-bash-code-for-me%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