Make a directory and change to it
$begingroup$
A basic shell function to create a directory and change to it goes like this:
mkcd () { mkdir "$1" && cd "$1"; }
This works well in many cases but breaks in unusual cases (e.g. if the argument begins with -
).
I'm writing a more sophisticated version. This version calls mkdir -p
to create parent directories if needed and just change to the directory if it already exists. It has these design goals:
- Work in any POSIX compliant shell.
- Cope with any file name.
- If the shell has logical directory tracking, where
foo/..
is the current directory even iffoo
is a symbolic link to a directory, then the function must follow that logical tracking: it must act as if thecd
builtin was called and magically created the target directory. - If a directory is created, it is guaranteed that the function changes into it, as long as there is no race condition (another process moving a parent directory, changing relevant permissions, …).
Here is my best current effort. Does it meet the goals above? Are there situations where the behavior is surprising?
mkcd () {
case "$1" in
*/..|*/../) cd -- "$1";; # that doesn't make any sense unless the directory already exists
/*/../*) (cd "${1%/../*}/.." && mkdir -p "./${1##*/../}") && cd -- "$1";;
/*) mkdir -p "$1" && cd "$1";;
*/../*) (cd "./${1%/../*}/.." && mkdir -p "./${1##*/../}") && cd "./$1";;
../*) (cd .. && mkdir -p "${1#.}") && cd "$1";;
*) mkdir -p "./$1" && cd "./$1";;
esac
}
bash shell unix
$endgroup$
add a comment |
$begingroup$
A basic shell function to create a directory and change to it goes like this:
mkcd () { mkdir "$1" && cd "$1"; }
This works well in many cases but breaks in unusual cases (e.g. if the argument begins with -
).
I'm writing a more sophisticated version. This version calls mkdir -p
to create parent directories if needed and just change to the directory if it already exists. It has these design goals:
- Work in any POSIX compliant shell.
- Cope with any file name.
- If the shell has logical directory tracking, where
foo/..
is the current directory even iffoo
is a symbolic link to a directory, then the function must follow that logical tracking: it must act as if thecd
builtin was called and magically created the target directory. - If a directory is created, it is guaranteed that the function changes into it, as long as there is no race condition (another process moving a parent directory, changing relevant permissions, …).
Here is my best current effort. Does it meet the goals above? Are there situations where the behavior is surprising?
mkcd () {
case "$1" in
*/..|*/../) cd -- "$1";; # that doesn't make any sense unless the directory already exists
/*/../*) (cd "${1%/../*}/.." && mkdir -p "./${1##*/../}") && cd -- "$1";;
/*) mkdir -p "$1" && cd "$1";;
*/../*) (cd "./${1%/../*}/.." && mkdir -p "./${1##*/../}") && cd "./$1";;
../*) (cd .. && mkdir -p "${1#.}") && cd "$1";;
*) mkdir -p "./$1" && cd "./$1";;
esac
}
bash shell unix
$endgroup$
add a comment |
$begingroup$
A basic shell function to create a directory and change to it goes like this:
mkcd () { mkdir "$1" && cd "$1"; }
This works well in many cases but breaks in unusual cases (e.g. if the argument begins with -
).
I'm writing a more sophisticated version. This version calls mkdir -p
to create parent directories if needed and just change to the directory if it already exists. It has these design goals:
- Work in any POSIX compliant shell.
- Cope with any file name.
- If the shell has logical directory tracking, where
foo/..
is the current directory even iffoo
is a symbolic link to a directory, then the function must follow that logical tracking: it must act as if thecd
builtin was called and magically created the target directory. - If a directory is created, it is guaranteed that the function changes into it, as long as there is no race condition (another process moving a parent directory, changing relevant permissions, …).
Here is my best current effort. Does it meet the goals above? Are there situations where the behavior is surprising?
mkcd () {
case "$1" in
*/..|*/../) cd -- "$1";; # that doesn't make any sense unless the directory already exists
/*/../*) (cd "${1%/../*}/.." && mkdir -p "./${1##*/../}") && cd -- "$1";;
/*) mkdir -p "$1" && cd "$1";;
*/../*) (cd "./${1%/../*}/.." && mkdir -p "./${1##*/../}") && cd "./$1";;
../*) (cd .. && mkdir -p "${1#.}") && cd "$1";;
*) mkdir -p "./$1" && cd "./$1";;
esac
}
bash shell unix
$endgroup$
A basic shell function to create a directory and change to it goes like this:
mkcd () { mkdir "$1" && cd "$1"; }
This works well in many cases but breaks in unusual cases (e.g. if the argument begins with -
).
I'm writing a more sophisticated version. This version calls mkdir -p
to create parent directories if needed and just change to the directory if it already exists. It has these design goals:
- Work in any POSIX compliant shell.
- Cope with any file name.
- If the shell has logical directory tracking, where
foo/..
is the current directory even iffoo
is a symbolic link to a directory, then the function must follow that logical tracking: it must act as if thecd
builtin was called and magically created the target directory. - If a directory is created, it is guaranteed that the function changes into it, as long as there is no race condition (another process moving a parent directory, changing relevant permissions, …).
Here is my best current effort. Does it meet the goals above? Are there situations where the behavior is surprising?
mkcd () {
case "$1" in
*/..|*/../) cd -- "$1";; # that doesn't make any sense unless the directory already exists
/*/../*) (cd "${1%/../*}/.." && mkdir -p "./${1##*/../}") && cd -- "$1";;
/*) mkdir -p "$1" && cd "$1";;
*/../*) (cd "./${1%/../*}/.." && mkdir -p "./${1##*/../}") && cd "./$1";;
../*) (cd .. && mkdir -p "${1#.}") && cd "$1";;
*) mkdir -p "./$1" && cd "./$1";;
esac
}
bash shell unix
bash shell unix
edited Apr 13 '17 at 12:37
Community♦
1
1
asked Jan 30 '13 at 22:25
GillesGilles
1,5081225
1,5081225
add a comment |
add a comment |
3 Answers
3
active
oldest
votes
$begingroup$
Some error messages may be confusing like:
$ mkcd /foo/../bar
mkcd:cd:3: no such file or directory: /foo/..
$ mkcd /bin/../bar
mkdir: cannot create directory `./bar': Permission denied
Probably not much you can do about that.
$endgroup$
1
$begingroup$
I don't find the message fromcd
particularly bad: at least it's true. On the other hand the message frommkdir
is wrong in that case.mkdir … 2>&1 | sed …
? Or rathererror=$(mkdir 2>&1 …) || …
to keep the return status.
$endgroup$
– Gilles
Jan 30 '13 at 23:46
add a comment |
$begingroup$
You should be able to get away with handling only two error cases (empty or no parameter) and three path possibilities: Absolute path, relative path which starts with ./
and other ("dangerous") paths:
mkcd() {
if [ -z "${1:-}" ]
then
printf '%sn' 'Usage: mkcd PATH'
return 2
fi
case "$1" in
/*|./*) break;;
*) set -- "./$1";;
esac
mkdir -p "$1" && cd "$1"
}
You won't need the --
separator. It might be surprising that mkcd foo/../bar
would create both directories if they don't exist, but that's more to do with mkdir
than the script.
Of course, this doesn't recursively simplify the path, which you'd need to do if you want to create the simplest absolute path defined (as printed by readlink -f
, which is not in POSIX). But this would be surprising behavior, since cd foo/../..
fails even when ../
exists.
$endgroup$
$begingroup$
If it was only a matter of the initial-
, thenmkdir -p -- "$1" && cd -- "$1"
would almost suffice (except for the oddball case of a directory named-
). The real complexity is in simulating the shell's logical directory tracking, when the argument containsfoo/..
wherefoo
is a symlink.
$endgroup$
– Gilles
Apr 3 '13 at 12:49
add a comment |
$begingroup$
I try this command mkcd --help
results in a new folder named --help
and it cd to this folder, but if I try mkdir --help
gives below output that I believe the correct behavior:
Usage: mkdir [OPTION]... DIRECTORY...
Create the DIRECTORY(ies), if they do not already exist.
Mandatory arguments to long options are mandatory for short options too.
-m, --mode=MODE set file mode (as in chmod), not a=rwx - umask
-p, --parents no error if existing, make parent directories as needed
-v, --verbose print a message for each created directory
-Z set SELinux security context of each created directory
to the default type
--context[=CTX] like -Z, or if CTX is specified then set the SELinux
or SMACK security context to CTX
--help display this help and exit
--version output version information and exit
GNU coreutils online help: <https://www.gnu.org/software/coreutils/>
Full documentation at: <https://www.gnu.org/software/coreutils/mkdir>
or available locally via: info '(coreutils) mkdir invocation'
I can't remove --help
folder after it created, zsh-5.7
.
New contributor
$endgroup$
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
return StackExchange.using("mathjaxEditing", function () {
StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
});
});
}, "mathjax-editing");
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "196"
};
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%2fcodereview.stackexchange.com%2fquestions%2f21082%2fmake-a-directory-and-change-to-it%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
$begingroup$
Some error messages may be confusing like:
$ mkcd /foo/../bar
mkcd:cd:3: no such file or directory: /foo/..
$ mkcd /bin/../bar
mkdir: cannot create directory `./bar': Permission denied
Probably not much you can do about that.
$endgroup$
1
$begingroup$
I don't find the message fromcd
particularly bad: at least it's true. On the other hand the message frommkdir
is wrong in that case.mkdir … 2>&1 | sed …
? Or rathererror=$(mkdir 2>&1 …) || …
to keep the return status.
$endgroup$
– Gilles
Jan 30 '13 at 23:46
add a comment |
$begingroup$
Some error messages may be confusing like:
$ mkcd /foo/../bar
mkcd:cd:3: no such file or directory: /foo/..
$ mkcd /bin/../bar
mkdir: cannot create directory `./bar': Permission denied
Probably not much you can do about that.
$endgroup$
1
$begingroup$
I don't find the message fromcd
particularly bad: at least it's true. On the other hand the message frommkdir
is wrong in that case.mkdir … 2>&1 | sed …
? Or rathererror=$(mkdir 2>&1 …) || …
to keep the return status.
$endgroup$
– Gilles
Jan 30 '13 at 23:46
add a comment |
$begingroup$
Some error messages may be confusing like:
$ mkcd /foo/../bar
mkcd:cd:3: no such file or directory: /foo/..
$ mkcd /bin/../bar
mkdir: cannot create directory `./bar': Permission denied
Probably not much you can do about that.
$endgroup$
Some error messages may be confusing like:
$ mkcd /foo/../bar
mkcd:cd:3: no such file or directory: /foo/..
$ mkcd /bin/../bar
mkdir: cannot create directory `./bar': Permission denied
Probably not much you can do about that.
answered Jan 30 '13 at 23:41
schsch
1112
1112
1
$begingroup$
I don't find the message fromcd
particularly bad: at least it's true. On the other hand the message frommkdir
is wrong in that case.mkdir … 2>&1 | sed …
? Or rathererror=$(mkdir 2>&1 …) || …
to keep the return status.
$endgroup$
– Gilles
Jan 30 '13 at 23:46
add a comment |
1
$begingroup$
I don't find the message fromcd
particularly bad: at least it's true. On the other hand the message frommkdir
is wrong in that case.mkdir … 2>&1 | sed …
? Or rathererror=$(mkdir 2>&1 …) || …
to keep the return status.
$endgroup$
– Gilles
Jan 30 '13 at 23:46
1
1
$begingroup$
I don't find the message from
cd
particularly bad: at least it's true. On the other hand the message from mkdir
is wrong in that case. mkdir … 2>&1 | sed …
? Or rather error=$(mkdir 2>&1 …) || …
to keep the return status.$endgroup$
– Gilles
Jan 30 '13 at 23:46
$begingroup$
I don't find the message from
cd
particularly bad: at least it's true. On the other hand the message from mkdir
is wrong in that case. mkdir … 2>&1 | sed …
? Or rather error=$(mkdir 2>&1 …) || …
to keep the return status.$endgroup$
– Gilles
Jan 30 '13 at 23:46
add a comment |
$begingroup$
You should be able to get away with handling only two error cases (empty or no parameter) and three path possibilities: Absolute path, relative path which starts with ./
and other ("dangerous") paths:
mkcd() {
if [ -z "${1:-}" ]
then
printf '%sn' 'Usage: mkcd PATH'
return 2
fi
case "$1" in
/*|./*) break;;
*) set -- "./$1";;
esac
mkdir -p "$1" && cd "$1"
}
You won't need the --
separator. It might be surprising that mkcd foo/../bar
would create both directories if they don't exist, but that's more to do with mkdir
than the script.
Of course, this doesn't recursively simplify the path, which you'd need to do if you want to create the simplest absolute path defined (as printed by readlink -f
, which is not in POSIX). But this would be surprising behavior, since cd foo/../..
fails even when ../
exists.
$endgroup$
$begingroup$
If it was only a matter of the initial-
, thenmkdir -p -- "$1" && cd -- "$1"
would almost suffice (except for the oddball case of a directory named-
). The real complexity is in simulating the shell's logical directory tracking, when the argument containsfoo/..
wherefoo
is a symlink.
$endgroup$
– Gilles
Apr 3 '13 at 12:49
add a comment |
$begingroup$
You should be able to get away with handling only two error cases (empty or no parameter) and three path possibilities: Absolute path, relative path which starts with ./
and other ("dangerous") paths:
mkcd() {
if [ -z "${1:-}" ]
then
printf '%sn' 'Usage: mkcd PATH'
return 2
fi
case "$1" in
/*|./*) break;;
*) set -- "./$1";;
esac
mkdir -p "$1" && cd "$1"
}
You won't need the --
separator. It might be surprising that mkcd foo/../bar
would create both directories if they don't exist, but that's more to do with mkdir
than the script.
Of course, this doesn't recursively simplify the path, which you'd need to do if you want to create the simplest absolute path defined (as printed by readlink -f
, which is not in POSIX). But this would be surprising behavior, since cd foo/../..
fails even when ../
exists.
$endgroup$
$begingroup$
If it was only a matter of the initial-
, thenmkdir -p -- "$1" && cd -- "$1"
would almost suffice (except for the oddball case of a directory named-
). The real complexity is in simulating the shell's logical directory tracking, when the argument containsfoo/..
wherefoo
is a symlink.
$endgroup$
– Gilles
Apr 3 '13 at 12:49
add a comment |
$begingroup$
You should be able to get away with handling only two error cases (empty or no parameter) and three path possibilities: Absolute path, relative path which starts with ./
and other ("dangerous") paths:
mkcd() {
if [ -z "${1:-}" ]
then
printf '%sn' 'Usage: mkcd PATH'
return 2
fi
case "$1" in
/*|./*) break;;
*) set -- "./$1";;
esac
mkdir -p "$1" && cd "$1"
}
You won't need the --
separator. It might be surprising that mkcd foo/../bar
would create both directories if they don't exist, but that's more to do with mkdir
than the script.
Of course, this doesn't recursively simplify the path, which you'd need to do if you want to create the simplest absolute path defined (as printed by readlink -f
, which is not in POSIX). But this would be surprising behavior, since cd foo/../..
fails even when ../
exists.
$endgroup$
You should be able to get away with handling only two error cases (empty or no parameter) and three path possibilities: Absolute path, relative path which starts with ./
and other ("dangerous") paths:
mkcd() {
if [ -z "${1:-}" ]
then
printf '%sn' 'Usage: mkcd PATH'
return 2
fi
case "$1" in
/*|./*) break;;
*) set -- "./$1";;
esac
mkdir -p "$1" && cd "$1"
}
You won't need the --
separator. It might be surprising that mkcd foo/../bar
would create both directories if they don't exist, but that's more to do with mkdir
than the script.
Of course, this doesn't recursively simplify the path, which you'd need to do if you want to create the simplest absolute path defined (as printed by readlink -f
, which is not in POSIX). But this would be surprising behavior, since cd foo/../..
fails even when ../
exists.
edited Apr 3 '13 at 12:19
answered Apr 3 '13 at 12:04
l0b0l0b0
4,2641023
4,2641023
$begingroup$
If it was only a matter of the initial-
, thenmkdir -p -- "$1" && cd -- "$1"
would almost suffice (except for the oddball case of a directory named-
). The real complexity is in simulating the shell's logical directory tracking, when the argument containsfoo/..
wherefoo
is a symlink.
$endgroup$
– Gilles
Apr 3 '13 at 12:49
add a comment |
$begingroup$
If it was only a matter of the initial-
, thenmkdir -p -- "$1" && cd -- "$1"
would almost suffice (except for the oddball case of a directory named-
). The real complexity is in simulating the shell's logical directory tracking, when the argument containsfoo/..
wherefoo
is a symlink.
$endgroup$
– Gilles
Apr 3 '13 at 12:49
$begingroup$
If it was only a matter of the initial
-
, then mkdir -p -- "$1" && cd -- "$1"
would almost suffice (except for the oddball case of a directory named -
). The real complexity is in simulating the shell's logical directory tracking, when the argument contains foo/..
where foo
is a symlink.$endgroup$
– Gilles
Apr 3 '13 at 12:49
$begingroup$
If it was only a matter of the initial
-
, then mkdir -p -- "$1" && cd -- "$1"
would almost suffice (except for the oddball case of a directory named -
). The real complexity is in simulating the shell's logical directory tracking, when the argument contains foo/..
where foo
is a symlink.$endgroup$
– Gilles
Apr 3 '13 at 12:49
add a comment |
$begingroup$
I try this command mkcd --help
results in a new folder named --help
and it cd to this folder, but if I try mkdir --help
gives below output that I believe the correct behavior:
Usage: mkdir [OPTION]... DIRECTORY...
Create the DIRECTORY(ies), if they do not already exist.
Mandatory arguments to long options are mandatory for short options too.
-m, --mode=MODE set file mode (as in chmod), not a=rwx - umask
-p, --parents no error if existing, make parent directories as needed
-v, --verbose print a message for each created directory
-Z set SELinux security context of each created directory
to the default type
--context[=CTX] like -Z, or if CTX is specified then set the SELinux
or SMACK security context to CTX
--help display this help and exit
--version output version information and exit
GNU coreutils online help: <https://www.gnu.org/software/coreutils/>
Full documentation at: <https://www.gnu.org/software/coreutils/mkdir>
or available locally via: info '(coreutils) mkdir invocation'
I can't remove --help
folder after it created, zsh-5.7
.
New contributor
$endgroup$
add a comment |
$begingroup$
I try this command mkcd --help
results in a new folder named --help
and it cd to this folder, but if I try mkdir --help
gives below output that I believe the correct behavior:
Usage: mkdir [OPTION]... DIRECTORY...
Create the DIRECTORY(ies), if they do not already exist.
Mandatory arguments to long options are mandatory for short options too.
-m, --mode=MODE set file mode (as in chmod), not a=rwx - umask
-p, --parents no error if existing, make parent directories as needed
-v, --verbose print a message for each created directory
-Z set SELinux security context of each created directory
to the default type
--context[=CTX] like -Z, or if CTX is specified then set the SELinux
or SMACK security context to CTX
--help display this help and exit
--version output version information and exit
GNU coreutils online help: <https://www.gnu.org/software/coreutils/>
Full documentation at: <https://www.gnu.org/software/coreutils/mkdir>
or available locally via: info '(coreutils) mkdir invocation'
I can't remove --help
folder after it created, zsh-5.7
.
New contributor
$endgroup$
add a comment |
$begingroup$
I try this command mkcd --help
results in a new folder named --help
and it cd to this folder, but if I try mkdir --help
gives below output that I believe the correct behavior:
Usage: mkdir [OPTION]... DIRECTORY...
Create the DIRECTORY(ies), if they do not already exist.
Mandatory arguments to long options are mandatory for short options too.
-m, --mode=MODE set file mode (as in chmod), not a=rwx - umask
-p, --parents no error if existing, make parent directories as needed
-v, --verbose print a message for each created directory
-Z set SELinux security context of each created directory
to the default type
--context[=CTX] like -Z, or if CTX is specified then set the SELinux
or SMACK security context to CTX
--help display this help and exit
--version output version information and exit
GNU coreutils online help: <https://www.gnu.org/software/coreutils/>
Full documentation at: <https://www.gnu.org/software/coreutils/mkdir>
or available locally via: info '(coreutils) mkdir invocation'
I can't remove --help
folder after it created, zsh-5.7
.
New contributor
$endgroup$
I try this command mkcd --help
results in a new folder named --help
and it cd to this folder, but if I try mkdir --help
gives below output that I believe the correct behavior:
Usage: mkdir [OPTION]... DIRECTORY...
Create the DIRECTORY(ies), if they do not already exist.
Mandatory arguments to long options are mandatory for short options too.
-m, --mode=MODE set file mode (as in chmod), not a=rwx - umask
-p, --parents no error if existing, make parent directories as needed
-v, --verbose print a message for each created directory
-Z set SELinux security context of each created directory
to the default type
--context[=CTX] like -Z, or if CTX is specified then set the SELinux
or SMACK security context to CTX
--help display this help and exit
--version output version information and exit
GNU coreutils online help: <https://www.gnu.org/software/coreutils/>
Full documentation at: <https://www.gnu.org/software/coreutils/mkdir>
or available locally via: info '(coreutils) mkdir invocation'
I can't remove --help
folder after it created, zsh-5.7
.
New contributor
New contributor
answered 1 hour ago
Tuyen PhamTuyen Pham
1011
1011
New contributor
New contributor
add a comment |
add a comment |
Thanks for contributing an answer to Code Review 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.
Use MathJax to format equations. MathJax reference.
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%2fcodereview.stackexchange.com%2fquestions%2f21082%2fmake-a-directory-and-change-to-it%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