Macos Bash Prompt For Input With Default

Introduction

Apple quietly added the powerful Z shell in Terminal. While the zsh prompt continues to appear bland like Bash shell, you can personalize it. Since the update to version 10.15 Catalina, macOS includes Z shell (zsh) as default instead of Bash in the Terminal app. That said, you still get the same black window with white text inside the Terminal. Bash PS1 prompt variable. PS1 is a primary prompt variable. Currently it holds u@ h: w $ special bash characters. This is the default structure of the bash prompt on many Linux systems and is displayed every time you log in using a terminal. Please see the following section 'Bash prompt special characters' for explanation of u, h, w.

We looked at one form of user input (command line arguments) in the previous section. Now we would like to introduce other ways the user may provide input to the Bash script. Following this we'll have a discussion on when and where is best to use each method.

After the mammoth previous section this one is much easier to get through.

Ask the User for Input

If we would like to ask the user for input then we use a command called read. This command takes the input and will save it into a variable.

read var1

Let's look at a simple example:

introduction.sh

  1. #!/bin/bash
  2. # Ask the user for their name
  3. echo Hello, who am I talking to?
  4. read varname
  5. echo It's nice to meet you $varname

Let's break it down:

  • Line 4 - Print a message asking the user for input.
  • Line 6 - Run the command read and save the users response into the variable varname
  • Line 8 - echo another message just to verify the read command worked. Note: I had to put a backslash ( ) in front of the ' so that it was escaped.
  1. ./introduction.sh
  2. Hello, who am I talking to?
  3. Ryan
  4. It's nice to meet you Ryan
  • Note: Ryan above is in italics just to show that it was something I typed in. On your terminal input will show up normally.

More with Read

You are able to alter the behaviour of read with a variety of command line options. (See the man page for read to see all of them.) Two commonly used options however are -p which allows you to specify a prompt and -s which makes the input silent. This can make it easy to ask for a username and password combination like the example below:

login.sh

  1. #!/bin/bash
  2. # Ask the user for login details
  3. read -p 'Username: ' uservar
  4. read -sp 'Password: ' passvar
  5. echo
  6. echo Thankyou $uservar we now have your login details
  • On lines 4 and 5 above we include the prompt within quotes so we can have a space included with it. Otherwise the user input will start straight after the last character of the prompt which isn't ideal from a readability point of view.
  1. ./login.sh
  2. Username: ryan
  3. Password:
  4. Thankyou ryan we now have your login details

More variables

With

So far we have looked at a single word as input. We can do more than that however.

cars.sh

  1. #!/bin/bash
  2. # Demonstrate how read actually works
  3. echo What cars do you like?
  4. read car1 car2 car3
  5. echo Your first car was: $car1
  6. echo Your second car was: $car2
  7. echo Your third car was: $car3
  1. ./cars.sh
  2. What cars do you like?
  3. Jaguar Maserati Bentley
  4. Your first car was: Jaguar
  5. Your second car was: Maserati
  6. Your third car was: Bentley
  7. ./cars.sh
  8. What cars do you like?
  9. Jaguar Maserati Bentley Lotus
  10. Your first car was: Jaguar
  11. Your second car was: Maserati
  12. Your third car was: Bentley Lotus

The general mechanism is that you can supply several variable names to read. Read will then take your input and split it on whitespace. The first item will then be assigned to the first variable name, the second item to the second variable name and so on. If there are more items than variable names then the remaining items will all be added to the last variable name. If there are less items than variable names then the remaining variable names will be set to blank or null.

Reading from STDIN

It's common in Linux to pipe a series of simple, single purpose commands together to create a larger solution tailored to our exact needs. The ability to do this is one of the real strenghs of Linux. It turns out that we can easily accommodate this mechanism with our scripts also. By doing so we can create scripts that act as filters to modify data in specific ways for us.

Bash accomodates piping and redirection by way of special files. Each process gets it's own set of files (one for STDIN, STDOUT and STDERR respectively) and they are linked when piping or redirection is invoked. Each process gets the following files:

  • STDIN - /proc/<processID>/fd/0
  • STDOUT - /proc/<processID>/fd/1
  • STDERR - /proc/<processID>/fd/2

To make life more convenient the system creates some shortcuts for us:

  • STDIN - /dev/stdin or /proc/self/fd/0
  • STDOUT - /dev/stdout or /proc/self/fd/1
  • STDERR - /dev/stderr or /proc/self/fd/2

fd in the paths above stands for file descriptor.

So if we would like to make our script able to process data that is piped to it all we need to do is read the relevant file. All of the files mentioned above behave like normal files.

summary

  1. #!/bin/bash
  2. # A basic summary of my sales report
  3. echo Here is a summary of the sales data:
  4. echo
  5. echo
  6. cat /dev/stdin | cut -d' ' -f 2,3 | sort

Let's break it down:

  • Lines 4, 5, 6 - Print a title for the output
  • Line 8 - cat the file representing STDIN, cut setting the delimiter to a space, fields 2 and 3 then sort the output.
  1. cat salesdata.txt
  2. Fred apples 20 May 4
  3. Susy oranges 5 May 7
  4. Mark watermelons 12 May 10
  5. Terry peaches 7 May 15
  6. cat salesdata.txt | ./summary
  7. Here is a summary of the sales data:
  8. apples 20
  9. oranges 5
  10. peaches 7
  11. watermelons 12

So which should I use?

So we now have 3 methods for getting input from the user:

  • Command line arguments
  • Read input during script execution
  • Accept data that has been redirected into the Bash script via STDIN

Which method is best depends on the situation.

You should normally favor command line arguments wherever possible. They are the most convenient for users as the data will be stored in their command history so they can easily return to it. It is also the best approach if your script may be called by other scripts or processes (eg. maybe you want it to run periodically using CRON).

Sometimes the nature of the data is such that it would not be ideal for it to be stored in peoples command histories etc. A good example of this is login credentials (username and password). In these circumstances it is best to read the data during script execution.

If all the script is doing is processing data in a certain way then it is probably best to work with STDIN. This way it can easily be added into a pipeline.

Sometimes you may find that a combination is ideal. The user may supply a filename as a command line argument and if not then the script will process what it finds on STDIN (when we look at If statements we'll see how this may be achieved). Or maybe command line arguments define certain behaviour but read is also used to ask for more information if required.

Ultimatately you should think about 3 factors when deciding how users will supply data to your Bash script:

  • Ease of use - which of these methods will make it easiest for users to use my script?
  • Security - Is there sensitive data which I should handle appropriately?
  • Robustness - Can I make it so that my scripts operation is intuitive and flexible and also make it harder to make simple mistakes?

Summary

read varName
Read input from the user and store it in the variable varName.
/dev/stdin
A file you can read to get the STDIN for the Bash script
Usability
Your choice of input methods will have an impact on how useable your script is.

Activities

Let's dabble with input.

  • Create a simple script which will ask the user for a few pieces of information then combine this into a message which is echo'd to the screen.
  • Add to the previous script to add in some data coming from command line arguments and maybe some of the other system variables.
  • Create a script which will take data from STDIN and print the 3rd line only.
  • Now play about with creating a script which will behave as a filter. Create a script which will rearrange the output of the command ls -l in a useful way (eg maybe you only print the filename, size and owner) (Hint: awk can be useful here).

From Wikipedia:

A Unix shell is a command-line interpreter or shell that provides a traditional user interface for the Unix operating system and for Unix-like systems. Users direct the operation of the computer by entering commands as text for a command line interpreter to execute or by creating text scripts of one or more such commands.

Macos Bash Prompt For Input With Default Ip

List of shells

Shells that are more or less POSIX compliant are listed under #POSIX compliant, while shells that have a different syntax are under #Alternative shells.

POSIX compliant

These shells can all be linked from /usr/bin/sh. When Bash, mkshAUR and zsh are invoked with the sh name, they automatically become more POSIX compliant.

  • Bash — Bash extends the Bourne shell with command-line history and completion, indexed and associative arrays, integer arithmetic, process substitution, here strings, regular expression matching and brace expansion.
https://www.gnu.org/software/bash/ || bash
  • Dash — Descendant of the NetBSD version of the Almquist SHell (ash). A fast POSIX-compliant shell that aims to be as small as possible.
http://gondor.apana.org.au/~herbert/dash/ || dash
Macos
  • KornShell (ksh) — The KornShell language is a complete, powerful, high-level programming language for writing applications, often more easily and quickly than with other high-level languages. This makes it especially suitable for prototyping. ksh has the best features of the Bourne shell and the C shell, plus many new features of its own. Thus ksh can do much to enhance your productivity and the quality of your work, both in interacting with the system, and in programming. ksh programs are easier to write, and are more concise and readable than programs written in a lower level language such as C.
http://www.kornshell.com || See the article.
With
  • Yash — Yet another shell, is a POSIX-compliant command line shell written in C99 (ISO/IEC 9899:1999). Yash is intended to be the most POSIX-compliant shell in the world while supporting features for daily interactive and scripting use.
https://yash.osdn.jp || yashAUR
  • Zsh — Shell designed for interactive use, although it is also a powerful scripting language. Many of the useful features of Bash, ksh, and tcsh were incorporated into Zsh; many original features were added. The introductory document details some of the unique features of Zsh.
https://www.zsh.org/ || zsh
Tip: POSIX and Bash scripts can be linted with shellcheck.

Alternative shells

  • C shell (tcsh) — Command language interpreter usable both as an interactive login shell and a shell script command processor. It includes a command-line editor, programmable word completion, spelling correction, a history mechanism, job control and a C-like syntax.
https://www.tcsh.org || tcsh
  • Elvish — Elvish is a modern and expressive shell, that can carry internal structured values through pipelines. This feature makes possible avoiding a lot of complex text processing code. It features an expressive programming language, with features like exceptions, namespacing and anonymous functions. It also has a powerful readline which checks the syntax while typing, and syntax highlighting by default.
https://elv.sh || elvishAUR
  • fish — Smart and user-friendly command line shell. Fish performs full-color command line syntax highlighting, as well as highlighting and completion for commands and their arguments, file existence, and history. It supports complete-as-you-type for history and commands. Fish is able to parse the system's man pages in order to determine valid arguments for commands, allowing it to highlight and complete commands. Easy last-command revision can be done using Alt+Up. The fish daemon (fishd) facilitates synchronized history across all instances of fish, as well as universal and persistent environment variables. Additionally, fish features significantly simplified programming syntax and control flow (similar to ruby). For more information, see the tutorial.
https://fishshell.com/ || fish
  • ion — Ion is a modern system shell that features a simple, yet powerful, syntax. It is written entirely in Rust, which greatly increases the overall quality and security of the shell, eliminating the possibilities of a ShellShock-like vulnerability, and making development easier. It also offers a level of performance that exceeds that of Dash, when taking advantage of Ion's features. While it is developed alongside, and primarily for, RedoxOS, it is a fully capable on other *nix platforms. For more details lookup its manual.
https://gitlab.redox-os.org/redox-os/ion/ || ion-gitAUR
  • Nash — Nash is a system shell, inspired by plan9 rc, that makes it easy to create reliable and safe scripts taking advantages of operating systems namespaces (on linux and plan9) in an idiomatic way.
https://github.com/NeowayLabs/nash || nash-gitAUR
  • Oh — Unix shell written in Go. It is similar in spirit but different in detail from other Unix shells. Oh extends the shell's programming language features without sacrificing the shell's interactive features.
Macos bash prompt for input with default ip
https://github.com/michaelmacinnis/oh || oh-gitAUR
  • PowerShell — PowerShell is an object-oriented programming language and interactive command line shell, originally written for and exclusive to Windows. Later on, it was open sourced and ported to macOS and Linux.
https://github.com/PowerShell/PowerShell || powershellAUR
  • rc — Command interpreter for Plan 9 that provides similar facilities to UNIX’s Bourne shell, with some small additions and less idiosyncratic syntax.
http://doc.cat-v.org/plan_9/4th_edition/papers/rc || 9base
  • xonsh — Python-powered shell with additional shell primitives that you are used to from Bash and IPython.
https://xon.sh/ || xonsh

Changing your default shell

After installing one of the above shells, you can execute that shell inside of your current shell, by just running its executable. If you want to be served that shell when you login however, you will need to change your default shell.

To list all installed shells, run:

And to set one as default for your user do:

If you are using systemd-homed, run:

where full-path-to-shell is the full path as given by chsh -l.

If you now log out and log in again, you will be greeted by the other shell.

Tip: chsh uses /etc/shells as reference. If a recently installed shell is not present on the list, it can be manually added to this file.

Login shell

A login shell is an invocation mode, in which the shell reads files intended for one-time initialization, such as system-wide /etc/profile or the user's ~/.profile or other shell-specific file(s). These files set up the initial environment, which is inherited by all other processes started from the shell (including other non-login shells or graphical programs). Hence, they are read only once at the beginning of a session, which is, for example, when the user logs in to the console or via SSH, changes the user with sudo or su using the --login parameter, or when the user manually invokes a login shell (e.g. by bash --login).

See #Configuration files and the links therein for an overview of the various initialization files. For more information about login shell, see also Difference between Login Shell and Non-Login Shell? and Why a 'login' shell over a 'non-login' shell? on Stackexchange.

Configuration files

To autostart programs in console or upon login, you can use shell startup files/directories. Read the documentation for your shell, or its ArchWiki article, e.g. Bash#Configuration files or Zsh#Startup/Shutdown files.

See also Wikipedia:Unix shell#Configuration files for a comparison of various config files of various shells.

/etc/profile

Upon login, all Bourne-compatible shells source /etc/profile, which in turn sources any readable *.sh files in /etc/profile.d/: these scripts do not require an interpreter directive, nor do they need to be executable. They are used to set up an environment and define application-specific settings.

Standardisation

Macos Bash Prompt For Input With Default

It is possible to make (some) shells configuration files follow the same naming convention, as well as supporting some common configuration between the shells.

See the article about this and the related repository. See also xsh.

Input and output

See also GregsWiki and I/O Redirection.

  • Redirections truncate files before commands are executed: will therefore not work as expected. While some commands (sed for example) provide an option to edit files in-place, many do not. In such cases you can use the sponge(1) command from the moreutils package.
  • Because cat is not built into the shell, on many occasions you may find it more convenient to use a redirection, for example in scripts, or if you care a lot about performance. In fact < file does the same as cat file.
  • POSIX-compliant shells support Here Documents:

Macos Bash Zsh

  • Shell pipelines operate on stdout by default. To operate on stderr(3) you can redirect stderr to stdout with command 2>&1 | othercommand or, for Bash 4, command |& othercommand.
  • Remember that many GNU core utilities accept files as arguments, so for example grep pattern < file is replaceable with grep patternfile.

Macos Bash Prompt For Input With Default Keyboard

See also

  • Evolution of shells in Linux on the IBM developerWorks
  • terminal.sexy — Terminal Color Scheme Designer
  • Hyperpolyglot — Side-by-side comparison of shell syntaxes
  • UNIX Power Tools — General command-line tool usage
  • commandlinefu.com — Command-line snippets sharing

Macos Bash Prompt For Input With Default Browser

Retrieved from 'https://wiki.archlinux.org/index.php?title=Command-line_shell&oldid=671177'