Skip to content

Instantly share code, notes, and snippets.

/good-shell.md Secret

Created September 9, 2014 21:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save anonymous/005b1a4a0f8869022107 to your computer and use it in GitHub Desktop.
Save anonymous/005b1a4a0f8869022107 to your computer and use it in GitHub Desktop.
A good shell?

A good shell

I started wondering today, why are we using arcane shells? Don't get me wrong, bash, zsh, fish, I like them all, but can't we do better by now? What do I mean by better? Short answer - drop the C. Long answer - let me ask a couple more questions:

  1. If I want to write a function that counts something, why do I have to return it as a string? And how do I return it in the first place? By echoing it and capturing that in a var? By setting a global variable? By using eval tricks?
  2. If I want to know a file's extension, why do I have to manipulate strings?
  3. What the hell is this? ${#files[@]}

For simple scripting these are non-issues but not many people enjoy writing e.g. bash scripts that get over 1k lines. It's just too tedious and error prone. What I'm looking for is simple:

  • To count the files in the current directory I don't want to say find . -type f -maxdepth 1 | wc -l and listen to people preaching me this is still wrong because filenames can contain newlines. That's my problem in the first place, I had no intention to count lines, I just want the number of files in the folder. I want to be able to say currentDir.files.count or length (files (dir ".")) etc.
  • To get the extension of a file I don't want to say "${file##*.}" and start wondering what if my file doesn't have one to begin with. I want to say file.extension or getExt file and move on.
  • To work with running processes I don't want to have ps, pgrep, kill etc., I want to have a list of running processes and be able to filter on them by name, uptime, user etc., create a report, batch kill them, you get the point.

The question aimed at you, reader, is - why aren't we doing this? Why aren't there shells/repls/clis written in python/ruby/haskell/lisp/... ? What is stopping us?

@swiftgeek
Copy link

@jcelerier
Copy link

Well you can always use python as an interactive shell ;p

@boardstretcher
Copy link

I've made this argument in the past as well. Best as I can understand it,. it comes down to what an 'operating system' is. Prepare for a big 'IMO' statement.

Windows is an all-in-one operating system and is totally capable of doing the things that you mention because there is one group responsible for the over all, connected system.

Fedora is not an 'operating system.' It is a distribution that ties together a Kernel, filesystem and utilities. They are all disparate, managed by different teams, and projects. Linux isn't a central OS like Windows.

I don't know if that makes sense, but to me, that is the big difference, and the reason behind the vast amount of utilities to interact with files in Linux.

@bartonski
Copy link

As jcelerier said, there's no reason why you can't replace (fi|ba|[cz])sh with python, Perl::Shell, ri, or your favorite repl... just add the path to the shell on separate line in /etc/shells, then use use chsh to set program as your interactive shell.

POSIX shell and its children are not great programming languages, but they are, by and large, very good command line interfaces... just as you would not want to write a ten-thousand line shell script, writing a one line perl or python script runs up against the limitations of the language ... it is, of course possible to pipe data, redirect output to files and launch programs from scripting languages, but not with anywhere nearly the brevity and cognitive efficiency of the shell -- in 30 seconds or less, how would you do this in your scripting language of choice?

tar cf - ./src/ | uuencode | mail -s 'CS 101 assignment 7' bsmith@foo.edu

To be fair, the only shell syntax there is |, but that's kind of my point ... a lot of what the shell does is stay the hell out of the way, providing just enough structure to string commands together, and it doesn't care what language they're written in.

The other thing that the shell provides for everyday use is creature comforts such as tab completion, prompts, command substitution, command line editing (set -o vi or set -o emacs)...

The shell is a good enough programming language that if I have 20 or 30 commands that I do all the time, I can chock them into a file, throw a conditional and a loop or three, and save myself hours of typing. I would argue that making it a better programming language would very likely make it a worse command line interface: the Unix philosophy dictates "Do one thing well" -- the shell is very good at being a command line interface. Let it be that. If you want better tools for counting files in a directory, taking file extensions, write them, then call them from the shell.

Keep in mind, because shells are something that people use every day, they tend to get stuck in our heads in funny ways -- all of my high power geek friends say that zsh is a fountain of awesome hacks; indeed I've seen some of the shiny stuff it can do -- but I've been using bash since 1999, and zsh's tab completion bugs the snot out of me -- I've been told that a) I can change it and b) stay the course, it's awesome when you get used to it... but alas no. I'll stick with bash... and of course, that's just a tiny piece of the shell, there are dozens of other details that make the shell just so...

Would it be awesome to be able to be able to do tab completion to kill processes in the shell from the command line? Yes. Enough to make me switch shells? No.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment