How bad is the Windows command line really?(blog.nullspace.io) |
How bad is the Windows command line really?(blog.nullspace.io) |
It doesn't even have a logical history. Despite having used it for many years, I still don't understand why when I type one command (eg make), and then another (eg out.exe), I have to toggle between pressing up or pressing down from the new command-prompt to access the previous commands.
I can't make the window more than 80-characters wide dynamically. (I don't want to change settings and restart the program to get the width to change.) So any time I want to copy and paste one of the infamous wall-of-text C++ template errors, I have to waste a lot of time reformatting the text.
Copy-and-paste as well is just complete garbage that takes forever.
I have to dump batch files into a folder in PATH because there's no alias support nor .profile startup script.
I can't color-code the prompt separately for visibility. There's no tab-completion. There's no shell escaping backticks. On and on.
Batch scripts are just hopelessly broken. It really feels like we're abusing the hell out of them to do things they were never intended to do. The language is closer to Malbolge than C.
PowerShell is a whole other can of worms. I don't care for it either, but that'd be a separate discussion.
Bash on Windows sounded promising, up until "Windows 10 only" and "doesn't play nice with the regular Windows environment."
> It doesn't even have a logical history. Despite having used it for many years, I still don't understand why when I type one command (eg make), and then another (eg out.exe), I have to toggle between pressing up or pressing down from the new command-prompt to access the previous commands.
With readline-style editing, as in bash, when you go back to an earlier command and re-run it, it is added to the end of the history and your "position" in the history is reset to the end. So if you want to go back to an earlier command again, you always hit "up".
In cmd.exe, when you go back to an earlier command and re-run it, you are simply going back to that earlier position in the history. When you run it, your location in the history is now immediately after the command you just ran. So to run the following command again, you now hit "down" rather than "up".
I think it's pretty logical and I actually quite like it (after the first half an hour of familiarisation, each time I have to use it). It's just different.
I also genuinely like PowerShell, but I'm with you on everything else.
Interesting! I never realized the logic behind it, thanks for expanding on it.
I definitely don't care for it at all. Much easier for my mind to think of the list of previous commands as a straight list, than trying to conceptualize 'where I am at' in my list of previous commands, and how executing a new command would then jump me somewhere else entirely. But I'll respect your difference of opinion.
> I also genuinely like PowerShell
To expand on this. As a Unix user with decades of experience writing shell, I find it easier to write a shell script than a PowerShell one for any given job. But I am a lot more confident that the PowerShell one will work correctly.
I take care with argument handling and the like in my scripts, but I still feel that testing a shell script with a specific set of inputs only really tells me whether it works with that set of inputs. It's almost certainly possible to craft an alternative set of inputs that will break it. I don't feel that way about PowerShell.
On the other hand, I do find it much easier to reason about performance with shell scripts. Their simple streaming structure parallelises well and the individual commands have generally predictable performance and scaling characteristics. I'm a lot less confident about that aspect of PowerShell.
https://msdn.microsoft.com/en-us/library/windows/desktop/ms6...:
"Console aliases are used to map source strings to target strings. For example, you can define a console alias that maps "test" to "cd \a_very_long_path\test". When you type "test" at the command line, the console subsystem expands the alias and executes the specified cd command. To define a console alias, use Doskey.exe to create a macro, or use the AddConsoleAlias function."
https://www.microsoft.com/resources/documentation/windows/xp...:
"Executing registry subkeys
If you do not specify /d in string, Cmd.exe looks for the following registry subkeys: HKEY_LOCAL_MACHINE\Software\Microsoft\Command Processor\AutoRun\REG_SZ HKEY_CURRENT_USER\Software\Microsoft\Command Processor\AutoRun REG_EXPAND_SZ If either one or both registry subkeys are present, they are executed before all other variables."
"There's no shell escaping backticks."
https://technet.microsoft.com/en-us/library/bb490909.aspx:
"Iterating and file parsing Use file parsing to process command output, strings and file content. […] for /F ["ParsingKeywords"] {%% | %}variable in ('command') do command [CommandLineOptions]"
Good UI? I've seen better. It also doesn't affect the conclusion that the cmd shell is bad, but the functionality does exist in some, often weirdly limited, form.
> I can't make the window more than 80-characters wide dynamically.
Windows 10 fixes this. You can resize the window and it wraps text better than any other terminal out there.
> Copy-and-paste as well is just complete garbage that takes forever.
Turn on Quick Edit. Now drag to select and right click to copy.
> There's no tab-completion.
Tab completion for filepaths works quite well for me.
Don't want to derail with Windows 10 arguments, but for me, that's a total deal breaker at this time. But thanks for pointing it out! Now if I find out Windows 10 can handle LF-formatted text in Notepad, I'll have to check and see if Hell froze over :P
> Turn on Quick Edit. Now drag to select and right click to copy.
It's not just having to go to the menu to click edit, it's that it bounds selections as a rectangular box when you paste the results. I also don't like the way quick-edit is so quick to select white blocks just by clicking in the window without dragging. Then to get rid of it, I have to right-click and kill whatever was in my clipboard. A bit OCD there, but ... I like bash a whole lot more. Normal text highlight, middle-click to paste what was highlighted elsewhere, and it's formatted properly. This is especially important when copying those 200-character long C++ template error messages.
> Tab completion for filepaths works quite well for me.
...... indeed there is. How in the world did I miss this?! Very sorry, I can't edit the parent post to fix this now.
Command line + mouse = GUI, not command line.
It is because the shell history has its own completely invisible cursor, and the cursor is not reset after a command. So when you press <up> three times, then press <enter>, your history cursor is still at -3 (actually, -4). If you then want to move to command -2, you need to press <down> instead of <up>.
The real fun comes when you edit commands in your history (so press <up>, then edit the command line). I'm still not quite sure how Microsoft handles that.
Also, you can use F7 to browse your command history - that may help a bit.
1. The parser allows modifying a .bat file during its execution and having those changes execute without restarting the Batch interperter. [1] This is in keeping with the rationale for batch processing -- facilitating serial execution of computationally expensive operations.
2. The Batch interpreter allows self modifying code.[2] In the early 1980's when Batch was designed, sophisticated COBOL programmers might have felt right at home. Lisper's were probably more hit and miss.
This is a case where historical context is useful. Today, it might perhaps be worth mentioning Powershell in a discussion of the Windows command line. Batch was the DOS command line and exists in Windows for evolutionary reasons.
In the days when abundant RAM and fast CPU speeds were prefixed with "mega" and distributed computing often happened at BAUD rates, not restarting a process was a big deal. More importantly, then as today, the execution speed of the batch interpreter was not a critical section of a batch process.
[1]: https://stackoverflow.com/questions/906586/changing-a-batch-...
Try type utf8Encoded.txt > out.txt in cmd.exe and posh. Cmd works and posh fs it up.
And after you do figure out utf8 encoding in posh, it'll always add a BOM just to screw you
[IO.File]::WriteAllLines($filename, $content)
(from https://stackoverflow.com/questions/5596982/using-powershell...)
Powershell is like a poor Java/C# interpreter instead of a quick and dirty shell.
You can see the difference in philosophy here, cmd (and bash, to a certain extent) are simple and don't try to do sneaky things silently, even if it means you might have to do a little more yourself e.g. performing character set translations explicitly. The behaviour is straightforward and predictable. PS attempts to be more "user-friendly" by doing some hidden conversions presumably so the user doesn't have to explicitly do character set translations, and when it works it works well; but when it fails, it fails spectacularly.
I was trying to run a Bash script from a Git repo mounted in a Docker container. When running the Bash script, I kept getting all kinds of errors. I ran the exact same script in the same Docker container on a different Linux computer that had cloned the repo. It turns out the \r Windows line endings (which I later normalized in Git settings) caused my script to barf.
Though honestly, Windows just doesn't even matter any more to me, I haven't needed to touch an MS product in years...
I've never gotten into PowerShell but I have absolute respect for the concept behind it, and how much more advanced it is than any shell you can find on UNIX. Think about it: instead of piping several commands through an unspecified string protocol that varies between each command (essentially what UNIX does), you are now piping real language objects in a uniform binary protocol defined by the shell itself.
Which is in fact a bad idea, because in order for stdin to accept objects and stdout to output objects, now those commands have to be powered by PowerShell and .NET. In other words you're in a very finite and closed environment that does not interoperate with the outside world.
You know, love or hate Unix, but the fact remains that this family of operating systems, including its command line, has survived the test of time. And it has done so because it has at its core a set of philosophical principles. And one of those is that programs that handle text streams are preferred, being highly interoperable, as text is a universal interface [1]. And you know it's funny how people loathe Unix, but at the same time rediscover its principles (and often implement them badly) again and again.
Configuration customization isn't really needed, only the usual date.timezone to get rid of the warning (and hell, this is annoying! can't PHP just use the OS-provided time zone?!), and in extremely rare cases the memory limit and max_execution_time.
You dont even need to give your software a ".exe" extension to run code.
Just rename a program removing its .exe extension, then call it from the command line. It will run!
Its perhaps better to compare dos BATch files with bash.
only 600kb to enjoy your sanity back
For the moment, I'm still stuck with Cygwin, shaking my head a bit too.
I'm a Microsoft fanboy and I find Python far more structured and faster than any of the above for anything beyond the most simple shell scripts. (If only the inventor of PowerShell had spent ten minutes outside the Microsoft ecosystem before locking himself in a seafoam green office for two years...)
Doesn't solve the IT admin scenarios PowerShell is good for but I don't go there. And if I did, I'd use C# anyway. No need to learn a new language to loop and call objects, that's solved.
With the .NET Core stuff, I'm using C# and Microsoft.DotNet.Cli.Utils and the end result is briefer and saner than Python argparse, and file operations work great cross platform. Less issues than even Python, plus I can use LINQ to sort and remove dupes. Handy.
As for the "Windows command line" (cmd.exe) well, it still sucks. Console2 plus Clink and ... well, you'll still miss zsh on cygwin or what just works out of box on Mac... but, hey, it's a start.
... and it's all true.
http://www.os2museum.com/wp/dos/dos-1-0-and-1-1/dos-1-0-dir/
To a first approximation, I'd expect that 1980's Unix programmers would generally be working in environments more accepting of restarting a batch process when there was an error in the code, i.e. significantly less likely to hold a clerical or secretarial "TCP report" job in a regular commercial office. Though that split has become less likely, it's still pretty uncommon for a computer user with little control of their work environment and deadlines to be using *nix rather than Windows.
Batch was restricted by DOS, I wish I had never learned it, but it did come in handy for launching games.
Easy enough to fix by having the menu program put the run script (.bat file) into the Novell equivalent of each user's home directory, but it was a real WTF moment at first :-)
http://steve-yegge.blogspot.ca/2006/03/execution-in-kingdom-...
I don't deny that it is much more powerful than cmd, but it feels a lot like "emacs rather than vi" in its design, and I much prefer the latter (which would be more (ba)sh-like.)
* usable tab-completion: scrolling through all available cmdlets is a poor substitute, and usually increases my keypresses instead of decreasing it.
* workable history editing: if I edit a previous command, I must remember to never use tab completion again, because pressing <tab> halfway in a command erases everything following the cursor
* consistent interface: In a powershell shell window, I can use left mouse button to select and copy, right mouse button to paste. In command shell window, I must use right mouse button to select "Mark" in context menu before even left-mouse selection works. In powershell ISE, left mouse button selects but does not copy, right mouse button still opens a context menu.
My first impression of it? It went like this:
Task: you need to connect to Hyper-V VM console via Remote Desktop.
Hiccup: for that, you need to know it's GUID. How to find it out? Just run this handy posh script... (https://blogs.msdn.microsoft.com/virtual_pc_guy/2014/11/25/u...)
Another hiccup: That script does not work, it needs some library that's not loaded by default. Try to find out how.
Another hiccup: It does not load, because it breaks some policy, that's off by default. Investigate, what to do.
How it ended: forget it, I have better things to do than solve problems with Powershell. Look into VM files and find out, that it's one of the GUIDs there.
Result: Won't touch posh again and anyone singing about its virtues is getting promptly ignored.
Maybe it's not fair to Powershell, but the first impression counts.
I'll bite. What's holding you back? Ever since 7 / 8.1 got telemetry backported in, they're on equal footing with 10 from a privacy standpoint. I guess you could cherry-pick out which windows updates you want to install, but that's frankly unsustainable.
You may as well get the new WDDM, the new DirectX 12, the new virtual desktop support, the new command prompt, and all of that.
>if I find out Windows 10 can handle LF-formatted text in Notepad, I'll have to check and see if Hell froze over :P
It doesn't, and it hasn't :P
Love your work by the way. bsnes/higan is a significant contribution to the human race.
I primarily run FreeBSD. But when I run Windows, it's a fresh SP1 install with updates disabled. I am not worried about the safety of it. I have a firewall, behind a router, and I don't install much of anything. I just use Windows for chatting and browsing online, watching streaming media services, etc. If something were to become compromised, I'd just wipe the drive with nothing of value lost or stolen in the process. I have another Windows box that doesn't even have internet access that is solely used to build and release Windows ports of my software.
Telemetry is part of it. I also find the interface ugly as sin (duller than Windows 3.1), don't like how bloated it's becoming (Metro tiles, Cortana, etc), don't like how difficult it is to disable updates, etc.
To be honest, if I had my way, I'd be on Windows XP (classic mode) still for what I use Windows for. The main draw to 7 was that XP's 64-bit drivers were mostly garbage or just plain unavailable; and I have lots of RAM and like the speed boost for 64-bit software too much.
> Love your work by the way.
Thank you very much! But ...
> bsnes/higan is a significant contribution to the human race.
I don't know about all that o_O'
At the end of the day, it's just video games.
This. My preferred explanation for the difference between Unix and Windows for a long time has been "Unix assumes a lot of people are doing different things on one computer, all at the same time. Windows was designed with the mental model of a calculator."
OTOH, you'll spend way less time scraping stuff for regexs and actually just asking posh for fields. It's really, really worth learning.
Anyway, my experience is that touching Firefox's reader-mode icon in the address bar is usually faster than a boatload of formatting logic; produces more readability than a website's general optimization, and bypasses all the ancillary crap that people concerned enough to optimize for mobile tend to add.
\r\n, CR+LF historically speaking was the first, but \n, LF became dominant because of Unix.
However, the inconsistencies of this over time have become really annoying. My long term pet peeve is in VB.NET when I have to do this:
' This works - using the VB6 interop
Split(StringName,vbCrLf)
' This doesn't work - using the native .NET function
' because .split is only expecting a Char, and not a String)
StringName.Split(vbCrLf)
Really, really annoying.With that said, CR+LF is just inefficient, since doing both of those tasks together is what is overwhelmingly desired for a newline.
I get using \r without \n for fun rewriting of a current line of text on a terminal.
But has anyone (in recent years) honestly want a new line, without a carriage return?
And why did all the internet protocols settle on this? It's an extra 8bits that are unnecessary.
Interestingly, when manually making a multi-line string in Powershell, only the LF character ( `n ) is needed to make a new line. Using CRLF ( 'r'n ) gives identical behavior in most strings.
But as you said, this allowed (at least the illusion, on some machines) more total memory to work with.
Even in the late 1980's 8088 based systems were pretty typical and why IBM included the PS/2 25 and 30 in its initial product line.
Which is of course a big tangent off of "why/whence command.com & .BAT files" :-)
OS/2 and Windows were a big deal in virtualizing memory use in PC land, with widespread Linux use still "a few years" in the future. (and effective adoption of NextStep even further out)
% set -o vi
% # hit ESC to go into vi cmd mode, hit k a few times until
% # you get to this old command in your command history:
% longasscommand -with -params -i super.dont -w ant2 -type in -again
% # you want just the stuff from -params to ant2, so you
% # type "f-n" to get the cursor to -params, then "yf2"
% # to copy everything from there to -w ant2
% # now you type j a couple times to go back down to
% # the line you were working on:
% longasscommand -with -oh jesus -not this.shit -again
% # now you hit "f-nn" to put the cursor on the -not
% # type "dW." to get it just so:
% longasscommand -with -oh jesus -again
% # now you're ready to paste in your copy after jesus
% # so you type p, and it's inserted where you left the cursor:
% longasscommand -with -oh jesus -params -i super.dont -w ant2 -again
You can use screen or tmux to copy and paste from anything on the screen, including using the mouse. It's really out of the purview of bash, tho.Really handy tools on the Mac are pbpaste which sends any text in the system clipboard to stdout and pbcopy, which you can prolly guess at.
I don't know how I lived without knowing that this is a thing.
Edit: this is in reply to the comment at the same level of this one, can't hit reply on it
There's an anti-flamefest delay on comment threads: you can't reply to comments younger than a few (5?) minutes. However, if you go to the comment directly (click on the timestamp next to it), you do get the option to reply immediately.
When I bought the Amiga 500 in 1988, 8088 Turbo machines were still the entry level clone system. My vague recollection of the consumer and small business market was that that obtained for a couple of more years.