News for hackers. Stuff that matters.
Re:Become Shell Literate by tutfbhuf on Saturday December 12, 2020 @12:56PM (#25400081)
I wish that shell would be more sane.

I don't think that a shell should be a complete programming language. If you need a programming language, then better use one. There is xonsh if you are looking for something like this.

I think there should be a better bash with an very clean and consistent interface. Some of the most commonly used utils like awk '{ print $2}', sed, grep, sort, ... should be included out of the box to improve performance and to provide consistency across distributions.

Re:Become Shell Literate by theon144 on Saturday December 12, 2020 @01:20PM (#25400254)
> I wish that shell would be more sane.

Absolutely agreed, shell is in many respects terrible.

>I don't think that a shell should be a complete programming language.

On the contrary, I think shell should be a more complete programming language! Drop the stringly typing and add actual types (hence eliminating 80% of bothersome awksedgrep magic; yes, no need to tell me it's a real tall order), add proper error handling...

I truly value simplicity where possible, but I think that the primary interface that I use to communicate with my computer should be as powerful as possible. Numerous times I've built up a shell pipeline only to realize near the end that I need to do something that shell is horrible at, and had to redo the whole thing in Python from scratch. I cannot really see a reason to limit it.

>Some of the most commonly used utils like awk '{ print $2}', sed, grep, sort, ... should be included out of the box to improve performance and to provide consistency across distributions.

UNIX "philosophy" got a lot of things wrong, but not this one. These common utilities you mention are good especially when they're separate, because it's not the shell's job to improve performance, provide consistency, etc... of a dozen and a half different utilities, a number sure only to grow in time as people discover what commonly used thing they want in their shell. Though I'll give you that `awk '{ print $2 }'` should definitely be its own utility or a built-in.

Re:Become Shell Literate by ohthehugemanate on Saturday December 12, 2020 @02:30PM (#25400810)
This is exactly the idea behind Powershell. You don't pipe strings between commands, you pipe typed objects etc etc. I'm convinced that if it had better support on Linux it would usher in a new age if shells. As it is though, it would be hard to use it as a daily driver.[1]

[1] https://code.joejag.com/2020/a-month-with-powershell.html

Re:Become Shell Literate by geophile on Saturday December 12, 2020 @02:05PM (#25400582)
Check out my pandemic project, marcel: https://marceltheshell.org. It hits that spot you described: still a shell, but more strongly typed. Instead of bailing out and redoing everything in Python (when you reach the end of your pipeline), you can add a bit of Python code in your command.

For example, find all the .py files under the current directory, find the ones that have changed in the last day, and then print the lines (with their filenames) that define classes:

    ls -fr \
    | select (f: f.suffix == '.py' and now() - f.mtime < days(1)) \
    | read -l \
    | select (path, line: line.startswith('class '))
read -l reads and labels a file, i.e., filename -> stream of (filename, line in file)

(Yes, this is doable with find and awk, but this is just an accessible example that gets across the idea of Python functions on the command line.)

Re:Become Shell Literate by enriquto on Saturday December 12, 2020 @02:46PM (#25400980)
> Yes, this is doable with find and awk

You don't even need awk for that one:

    grep ^class `find . -mtime -1 | grep py$`
Maybe you could try to use an example where it really makes a difference? Some natural operation that would be very cumbersome with plain shell but is easy and direct with marcel. Otherwise many people may fail to see the point.
Re:Become Shell Literate by geophile on Saturday December 12, 2020 @03:30PM (#25401420)
Read a CSV file, foo.csv, and sort by the sum of the 4th and 7th columns (which are integers):

    read -c foo.csv | sort (*x: int(x[3]) + int(x[6]))
I suppose we could argue about what is a "natural" operation. Marcel grew out of a set of tasks that were "natural" in the domain I was working in. An important part of that domain was operating on databases, and clusters of nodes, and databases on those nodes. So marcel has features for those capabilities.

Partly, I was also scratching an itch: I prefer using Python to exploring the sublanguages of various shell commands. Much cleaner, in my opinion.

Re:Become Shell Literate by enriquto on Saturday December 12, 2020 @03:59PM (#25401658)
> Read a CSV file, foo.csv, and sort by the sum of the 4th and 7th columns (which are integers):

Yes, that's a much better example. Here the "obvious" shell solution involves using awk to compute the sum of the two columns and putting it as the first field, sorting by the first field, and then removing that field. I guess a "rosetta stone" of such examples (e.g. on the frontpage of the site) would make a strong case for the interest of marcel.

Re:Become Shell Literate by em500 on Sunday December 13, 2020 @03:37AM (#25405169)
Concretely,

    awk -F, -v OFS=, {print $2+$3, $1, $2, $3}' foo.csv  |  sort -n  |  cut -d, -f2-
Re:Become Shell Literate by enriquto on Sunday December 13, 2020 @06:35AM (#25405850)
I think this code does not fulfill the task: you need to sum columns 4 and 7, and keep the rest of the data intact in the output.
Re:Become Shell Literate by em500 on Sunday December 13, 2020 @09:02AM (#25406600)
You're right, that should be

      awk -F, -v OFS=, '{print $4+$7, $0}' foo.csv  |  sort -n -k1 -t, |  cut -f2- -d,

Explanation:

awk -F, -v OFS=, sets the input and output column separator to comma, '{print $4+$7, $0}' outputs the sum of column 4 and 7 before the rest of the line.

sort -n -k1 -t, sorts the file numerically on column 1, with comma separator.

cut -f2- -d, removes column 1, with comma separator.

This is of course not robust for general CSV files, but I don't think OPs marcel is either. A robust solution requires a proper CSV parser.

The biggest warts I see in the classic unix solution is that all the tools use different flags for the field separator.

edit: if you know that the csv doesn't contain tabs, you can omit some flags for a more concise

    awk -F, -v OFS='\t' '{print $4+$7,$0}'  foo.csv | sort -n -k1 | cut -f2-
since sort and cut default to tabs/whitespace as separators. If you're unsure about the contents of the CSV, you really need a proper CSV parser.
Re:Become Shell Literate by geophile on Sunday December 13, 2020 @01:13PM (#25408647)
> This is of course not robust for general CSV files, but I don't think OPs marcel is either. A robust solution requires a proper CSV parser.

I haven't tested corner cases, but marcel relies on the python csv module, which is probably better than any initial attempt at a parser that I could write in an hour.

This is what I meant about sublanguages. Many people, (myself included), would need to go to the man pages to find the necessary arguments to awk, sort, and cut. I find it much easier to just write a little Python, even if the end result involves more typing.

Re:Become Shell Literate by enriquto on Sunday December 13, 2020 @10:17AM (#25407097)
At the end, it doesn't look that bad. Of course using the csv format is a bad start in unix. Much better to convert everything to tsv and work from there. In that case the "obvious" shell solution is quite clear.

    <foo.tsv awk '{print $4+$7,$0}' | sort -n -k1 | cut -f2-
Re:Become Shell Literate by geophile on Saturday December 12, 2020 @02:08PM (#25400605)
Oh, and when you do bail out and go to Python, marcel's operators are available in a module (marcel.api), so that you can take your pipeline and move it into Python easily. E.g. here's the same example in Python:

    from marcel.api import *

    for path, line in (ls(file=True, recursive=True) |
                       select(lambda f: f.suffix == '.py' and 
                              now() - f.mtime < days(1)) |
                       read(label=True) |
                       select(lambda path, line: line.startswith('class '))):
        print(f'({path}: {line})
                       read(label=True)
Re:Become Shell Literate by willghatch on Sunday December 13, 2020 @12:32AM (#25404535)
Since everybody else is peddling their better shells, I'll drop a plug for mine: https://rash-lang.org

It's a shell embedded in the Racket programming language. If you're familiar with Xonsh, it's similar, but both more powerful and less polished. It allows easy, recursive mixing of shell code (not posix compatible, but with a similar feel) and Racket. Its interactive mode is not polished (I need to write a better line editor), but it works, and it's great for programming.

I haven't worked on it much lately (I need to wrap up other things to finish my PhD), but this weekend I added support for user-programmable substitutions with automatic cleanup. As an example, beyond common substitutions like process substitution (IE <() and >() in bash), I added a demo “closure substitution” form that allows you to send Racket functions to `find -exec`. Importantly, this is something that a user could add, because Rash is super extensible and malleable.

Shell is a great DSL, but there are huge advantages to having an embedded DSL rather than a stand-alone DSL. Rash inherits all the cool features of Racket and can be mixed with other Racket languages (eg. Typed Racket, Honu, etc), has advanced features like first-class delimited continuations and the world's most advanced macro system (which makes Rash possible), and any shell script can import functions from Racket's catalog of third-party packages. Embedded shells like Rash allow a shell script to be copied from interactions like you do with Bash, but then grow past the “rewrite in Python” stage gradually with no rewrite -- just a gradual transition from being more shell code to being more “normal” code.

Though I'm kicking myself for continually not getting around to rewriting all the documentation, which is still very poor.

Re:Become Shell Literate by alpaca128 on Saturday December 12, 2020 @01:51PM (#25400488)
Keeping those small utilities separate is definitely the right choice as it keeps everything very flexible. I could just replace grep with ripgrep in my workflow and suddenly get a drastically quicker search without having to change anything else. If all those features were integrated in the shell the user is more or less stuck with the whole package.

Which is also one of the reasons I prefer using Vim over Emacs; I can embed Vim in any terminal multiplexer of my choice and combine it with various terminal programs. Every single part of that environment is easy to understand and easy to replace with another program or script. It's less homogenous and consistent, but I am fine with that tradeoff. As one might guess I am not a big fan of IDEs.

Re:Become Shell Literate by akkartik on Saturday December 12, 2020 @01:15PM (#25400225)
I've been trying to build a computer with a single principled HLL included that can also double as a shell. There's also http://www.oilshell.org which _also_ tries to be compatible with existing shell. It also tries to include features from awk and sed: https://www.oilshell.org/blog/2016/11/13.html

If these design points turn out to be over-constrained and have to make major compromises, yes the next thing I would try would be a small separate language for shell.

Re:Become Shell Literate by chubot on Saturday December 12, 2020 @03:17PM (#25401296)
BTW I think the general idea of Oil's syntax is working out: start in "command mode", and then when you see the RHS of =, changing modes to Python-/JS- like expressions. There a few other cases where you switch to expression mode, like proc p(a, b) [1]

So far nobody has complained about any of this, I'm guessing because it looks very familiar, and that was intentional. Oil takes some pains to literally look like shell + Python syntactically, with better semantics.

I noticed that a few other shells are having problems with this command/expression distinction, and I discussed it like 3-4 years ago with Ilya Sher (of NGS) and a few other people. They were also having the same problem.

For example, does / mean a path separator or the division operator? Does * mean a glob or a multiplication? In Oil, this is no problem. It's obvious depending on the context.

Though I'm interested in more feedback on this, and the latest release is available to try as always :) https://www.oilshell.org/release/latest/

---

The awk and make integration is still doable but not done. Awk might require a notion of "lazy expressions" or "lazy arg lists", which would be shared with dplyr-like functionality. Oil's Zulip is open for discussion on these ideas :)

[1] https://www.oilshell.org/release/0.8.5/doc/command-vs-expres...

Re:Become Shell Literate by thrower123 on Saturday December 12, 2020 @01:23PM (#25400273)
If you think the unix shell sucks, try fucking around with the Windows shell - either of them. You're either in a world of legacy and inconsistency dating to DOS and the days of 8.3 filenames, or you're in the also wildly inconsistent, but very verbose, world of PowersHell.
Re:Become Shell Literate by geophile on Saturday December 12, 2020 @02:14PM (#25400667)
About powershell's verbosity: My pandemic project is yet another pipe-objects-instead-of-strings shell, marcel: https://marceltheshell.org. It's "home" is Linux, not Windows.

Marcel is also somewhat verbose. It exposes Python functions on the command line, so when you need to write such a function, it starts getting long. E.g. if you want to sort files by last time modified:

    ls | sort (f: f.mtime)
There are abstraction mechanisms to help deal with this. E.g. this defines a command to sort piped-in files by time.

    bytime = [sort (f: f.mtime)]
So you can then do this:

    ls | bytime
Still kind of wordy. I'm thinking about a way of having flags expand to filters. That would get things as compact as bash.
Re:Become Shell Literate by todd8 on Saturday December 12, 2020 @01:13PM (#25400211)
Yeah, Perl started out a bit like this. I never adopted it for myself or my company, but I did get a chance to have lunch with Larry Wall and talked to him about Perl. This was back when Perl was quite a young and promising language for a certain class of problems.

Perl had very good performance, despite being a "scripting" language, because so many of the tasks that a typical shell script might need to do were supported by built in features in the language (for example handling regular expressions, interacting with command line arguments, exec'ing other programs).

Today, once a shell script requires very much logic, I'm inclined to use Python. I know Python and find programming in it easier than Perl and bash and other shells. Furthermore, other programmers understand Python better than bash.

Re:Become Shell Literate by chubot on Saturday December 12, 2020 @02:03PM (#25400564)
Oil is making shell more sane, in a way that you can realistically adopt, since it runs existing shell scripts. See:

Four Features That Justify a New Unix Shell http://www.oilshell.org/blog/2020/10/osh-features.html

Re:Become Shell Literate by Closi on Saturday December 12, 2020 @01:24PM (#25400292)
> I think there should be a better bash with an very clean and consistent interface.

Absolutely! Some work should be put into making it way more intuitive. Having to remember what every flag means (which is different in every app!) is not intuitive at all.

By default there should be some sort of intelisense auto-complete which can also provide guidance on what on earth all the flags mean, and maybe eventually it could tell you what it expects to do before you run the command. For most users otherwise it ends up being "paste in this command you googled with a load of random flags you don't understand and won't remember"

Re:Become Shell Literate by dafoex on Saturday December 12, 2020 @01:35PM (#25400366)
Just suggested it in another comment, but Fish might be similar to what you describe. It has tab-completable flags that it gets from the manpages, and remembers and suggests previously run commands which might be close to the auto-complete you're after.
Re:Become Shell Literate by Closi on Saturday December 12, 2020 @06:39PM (#25402856)
Fish is better, but it still only gets 1/10th of the way.

Why does terminal have to look like terminal? Like why is the 1980's ASCII telnet style the only way to do this?

The ASCII fish image on boot and fully ASCII menus only reinforces again that this isn't a modern interface, its an improved 1980's interface.

Why, for example, can autocomplete not look like this? https://code.visualstudio.com/docs/editor/intellisense

Why do progress bars when you are downloading from pip not look something like this? (still in-line with the terminal like a sparkline) https://docs.microsoft.com/en-us/windows/win32/uxguide/progr...

Like surely everything doesn't have to be SO 1980's if we want shell to stay relevant.

Re:Become Shell Literate by southpawflo on Sunday December 13, 2020 @01:37AM (#25404772)
because then your shell will be slower than a snail.

for real though, after looking at your examples I feel that features like those would fall on your terminal emulator to bring to the table, not the shell itself.

specifically, I don't want to imagine trying to connect to a headless server during some crisis over bad wifi and have the shell think it needs to send a bunch of graphics to me.

Re:Become Shell Literate by mschrage on Sunday December 13, 2020 @01:54AM (#25404832)
This is exactly what I’ve been working on with Fig. Intellisense exists in every modern IDE but not the shell.

https://github.com/withfig/autocomplete

Re:Become Shell Literate by Aloha on Saturday December 12, 2020 @01:07PM (#25400170)
It wouldn't be coherently unixy if it was. Small tools that do a limited subset of things, and reliably take/output data from stdin/stdout is the way unix is done. sh is just the glue we use to tack it all together.

Bash (and other shells too) is like it is, because it's an accretion of 50 years of history rather than a singular top down design.

Re:Become Shell Literate by cle on Saturday December 12, 2020 @01:48PM (#25400464)
I think a misunderstood part of Emacs is that this is exactly what it is—-it’s just glue, but instead of being in a command-oriented environment, it’s in an editor-oriented environment. You run the same Unix tools but glue their results together into a text buffer with a full programming language that then lets you programmatically edit the results.

People joke about Emacs being an OS but it’s really just a different kind of shell, oriented towards text editing instead of issuing commands.

Re:Become Shell Literate by Aloha on Sunday December 13, 2020 @01:39AM (#25404781)
Without commenting on substance, Emacs is an application that rehomed itself on unix, but isnt a genetic unix application, Emacs was developed on ITS.
Re:Become Shell Literate by randomswede on Monday December 14, 2020 @11:08AM (#25419116)
Definitely originally. I suspect that a modern emacs has more unix under the hood than it has ITS under the hood.

I am not sure if we should care about the differentiation between TECO-Emacs on one hand and Elisp-Emacs on the other.

Re:Become Shell Literate by CJefferson on Saturday December 12, 2020 @01:13PM (#25400213)
One of the best things (in my opinion) shells could have done is do newline separated filenames instead of spaces, which would make filenames with spaces much easier to handle (you can have newlines in filenames, but in this magic world let's ban those).
Re:Become Shell Literate by chubot on Saturday December 12, 2020 @02:05PM (#25400581)
Oil fixes this problem with QSN: http://www.oilshell.org/blog/2020/10/osh-features.html#safe-...

You can have newlines in filenames, but you can also pass binary data with \0 if you want (it's 8 bit clean). Or you can use read -0 for a NUL delimiter, and eventually length-prefixed blobs with netstrings.

The way I now think of it is that Oil should have all 3 solutions to "the framing problem" in networking: delimiting, escaping, and length prefixing. So you can convert from one regime to the other by using shell.

Re:Become Shell Literate by enriquto on Saturday December 12, 2020 @01:15PM (#25400229)
That would pose problems also. The real solution, with no need to magic as you say, is to disallow spaces at the filesystem level (just like slashes and the null character are forbidden). For users typing filenames, this shouldn't be a problem, as those can be encoded e.g., as unicode's non-breaking space. Using space as a separator is a very important power, that other programming languages share. In what other programming language can you put spaces in variable names? In the shell, filenames are variable names! It is only natural that a space cannot appear inside a filename (but of course, most other unicode characters can).
Re:Become Shell Literate by jodrellblank on Saturday December 12, 2020 @01:32PM (#25400339)
> In what other programming language can you put spaces in variable names?

PowerShell; although you have to use long form to do it:

    PS C:\> ${var with spaces} = 1

    PS C:\> Get-Variable *space*

    Name                           Value                                                                                                       
    ----                           -----                                                                                                       
    var with spaces                1                                                                                                           



    PS C:\> ${var with spaces} + 2
    3
Re:Become Shell Literate by layer8 on Saturday December 12, 2020 @01:37PM (#25400385)
> In what other programming language can you put spaces in variable names?

In SQL, notably. Such identifiers need to be quoted, of course.

Re:Become Shell Literate by dragonwriter on Saturday December 12, 2020 @02:57PM (#25401082)
> In what other programming language can you put spaces in variable names?

ISTR that many dynamic languages allow this with dynamic assignment features, but you often need to use similar dynamic access functiona rather than simple variable access to access them.

Ruby also allows whitespace if it is unicode but not ASCII whitespace, without use of dynamic assignment/access methods.

SQL allows spaces in object names but requires quoting, similar to shell.

Re:Become Shell Literate by CJefferson on Saturday December 12, 2020 @01:25PM (#25400299)
This would require filenames became valid utf-8. This would be a good thing to do nowadays, irritatingly (having tried handling Unix filenames as utf 8 in the past), surprisingly many users have non-utf8 filenames.
Re:Become Shell Literate by a1369209993 on Saturday December 12, 2020 @07:48PM (#25403263)
> This would require filenames became valid utf-8.

No, it wouldn't; you'd just get EINVAL if you pass a filename containing "\x20" to open or other syscalls. If a application wants to use "\xC2\xA0" in a filename, it can do that, or it can not do that, same as currently. Same applies if it wants to use, say, "\xAA\xFF".

Re:Become Shell Literate by Serow225 on Saturday December 12, 2020 @08:41PM (#25403534)
You can have spaces in F# variable names and functions :)
Re:Become Shell Literate by dafoex on Saturday December 12, 2020 @01:46PM (#25400445)
I totally agree that file names shouldn't have spaces because they are variables, and I (usually) name all my files with camelBackNotation names as I was taught is best practice for variable names. That said, with every command I remember running, treating the file name like a string - e.g. "file name.png" - has worked whenever I encounter spaces, no escape characters required.
Re:Become Shell Literate by CJefferson on Saturday December 12, 2020 @02:48PM (#25401005)
The problem is shell is when I want to write something like 'find . | grep namepiece | xargs rm', or something like that. I can work around this by piling everything into the find, or in some cases by liberally spreading -0s around, but neither feel very "shell-like" to me.
Re:Become Shell Literate by enriquto on Saturday December 12, 2020 @03:27PM (#25401390)
Thus it seems that a filesystem that forbade spaces in its filenames would solve your problems with the shell? Sounds good to me!
Re:Become Shell Literate by lock-free on Saturday December 12, 2020 @01:35PM (#25400356)
I don't see a functional difference in denying spaces in paths from denying new lines in paths.

My dream OS would forbid path names that don't match \w in grep.

Re:Become Shell Literate by enriquto on Saturday December 12, 2020 @01:05PM (#25400156)
> I don't think that a shell should be a complete programming language.

What do you mean exactly? If you have pipes and lists (e.g., the lines on a file) you are Turing-complete and people can and will make arbitrary programs. How would you like, precisely, to restrict the shell language so that it is not Turing-complete?

Re:Become Shell Literate by tutfbhuf on Saturday December 12, 2020 @01:48PM (#25400468)
I mean shell should not be python, like xonsh. In my opinion it should not add programming language features (like types, futures, ADTs,...), but instead should clean up the existing built-ins + maybe little bit coreutils as built-ins.
Re:Become Shell Literate by enriquto on Saturday December 12, 2020 @02:19PM (#25400703)
Never heard about xonsh, it looks really cool. Seems like a step in the good direction (from python to shell). It needs a few steps more to attain the elegant perfection of the shell language, for example, removing this "type" stuff from the variables ;)
Re:Become Shell Literate by tannhaeuser on Saturday December 12, 2020 @02:21PM (#25400715)
Your wish has been granted: awk '{ print $2 }' can be replaced by 'cut -f2'. And all of the commands are part of the set of POSIX command-line utilities having been included on Unix systems since basically forever, with awk (the one true awk) having been introduced only in 1983 or so.
Re:Become Shell Literate by tedunangst on Saturday December 12, 2020 @02:31PM (#25400816)
cut doesn't use the same field delimiters as awk.
Re:Become Shell Literate by Scarbutt on Saturday December 12, 2020 @03:06PM (#25401169)
And awk doesn't let you easily select a range of fields like cut
Re:Become Shell Literate by IshKebab on Saturday December 12, 2020 @02:31PM (#25400823)
I agree. There's nushell which looks a lot more sane, so I have hope that we won't be stuck with insane tools from the 80s for the rest of time! Maybe people will stop deifying those old flawed tools too.
Re:Become Shell Literate by thyrsus on Saturday December 12, 2020 @01:02PM (#25400131)
If the data is small, then expressivness is more important. If the data is large, then multiple processes connected by pipes lets you employ more CPUs.
Re:Become Shell Literate by mooreds on Saturday December 12, 2020 @01:05PM (#25400155)
Have to pull this old chestnut out: https://adamdrake.com/command-line-tools-can-be-235x-faster-...

I am not the author of that piece, but the analysis is wonderful.