bash's echo command is broken

  Рет қаралды 81,378

Computing: the Details

Computing: the Details

Жыл бұрын

Bash's echo command is broken. You can't reliably print variable contents using echo.
This video explores how it's broken, and some things you can do to work around it.
There's even a demo of a bug in some other software caused by the strange behaviour of echo.
!!! Spoilers for the challenge below !!!
At the end of the video is this challenge:
make bash's echo print "-n" with no other characters, not even the newline, without using any other commands, without piping the output anywhere.
Some things people often try that don't work:
echo -n - -n
echo -n -- -n
unix commands often interpret a "-" or a "--" as "don't process any further arguments as options to the command, but as something less special". echo in bash does not do this. The first option above does work for zsh though, so points to zsh for making that work. The second option in that list works for fish, which imho has the most sensible and predictable echo implementation. Neither works for bash. bash just prints those dashes.
The things that do work for bash are as follows:
echo -en '\u002dn'
echo -e '-n\c'
The first option there uses an escape sequence to generate the dash, which is not interpreted at option parsing time, but comes much later, thus preventing bash interpreting it as an option.
The second one uses a very special escape sequence, "\c", which means "stop outputting at this point". Since "\" is not a valid echo option, the argument is not interpreted as special. It does not appear in the output, because it is the "stop now" escape sequence, therefore you just get the "-n".
You might be tempted to use the '\c' trick to try and enable reliable printing of variables, but actually this doesn't work. For example, the following might be tempting at first:
echo -e "$VAR
\c"
But remember that the "-e" means anything in VAR that looks like an escape sequence is now going to be interpreted by echo, and so the variable won't be printed correctly.

Пікірлер: 430
@computingthedetails
@computingthedetails Жыл бұрын
Correction: zipgrep is only broken sometimes. zipgrep works correctly on debian, for example. since zipgrep uses /bin/sh as the interpreter, the presence of this bug depends on what package provides /bin/sh on your system. The default for debian is to use dash to provide /bin/sh, in which case zipgrep works fine without my fix. On systems where /bin/sh is bash (for example Arch Linux defaults to this) then you will encounter this bug. Curiously, the posix spec explicitly allows implementation defined behaviour, so zipgrep is not even guaranteed to work on any posix compliant shell. Something that posix does specify is that '--' should not be considered special, and should just be printed. If '--' behaved as normal then I probably wouldn't have made this video. :)
@Redditard
@Redditard Жыл бұрын
your whispers made me break the rules of subscribing to a youtuber until they're recommended to me twice lol~ keep the good work uppp
@tacokoneko
@tacokoneko Жыл бұрын
here is my solution for the challenge echo -e '-n\c' alternate form to print new line if that's what is needed: echo -e '-n \c' did i do it right or i failed?
@tacokoneko
@tacokoneko Жыл бұрын
oh i read the description after i posted that so i see yes you consider mine a valid solution
@damnstupidoldidiot8776
@damnstupidoldidiot8776 Жыл бұрын
Or, implement zipgrep in C.
@codytubbs
@codytubbs Жыл бұрын
​@LunacyStudy the docs are broken. :) They don't even know what their own code is doing. The bash built-in echo and the coreutils echo both support the double dash to end parsing of args, it just also prints the double dash. Here's a good example ... try it with and without the double dash (also remove the double quotes around them, that's just to make youtube happy): echo -e "--" -E "\cxxx" | sed -r 's/^-{2} //'
@dgeoffri
@dgeoffri Жыл бұрын
the most obvious answer is echo -ne \\x2d\\x6e
@moth.monster
@moth.monster Жыл бұрын
@@jonathanleslie9100 I'm going to put a newline in a filename too just to spite you
@jonathanleslie9100
@jonathanleslie9100 Жыл бұрын
@@moth.monster LOL If I was heading up the project, I'd make you clean toilets with your toothbrush. 1294 sprintf(szTempstring 1295 ," Enter the name of the file here (all spaces and " 1296 "special characters will be replaced with underscores):" 1297 "" 1298 ); 1299 strcat(szBuffer, szTempstring); 41 int replace_special_character(char *str ){ 42 int i, flag = 0; 43 int n; 44 n=strlen(str); 45 for (i = 0; i < n; ++i){ 46 //checking each character of the string for special character. 47 if( str[i] == '!' || str[i] == '@' || str[i] == '#' || str[i] == '$' 48 || str[i] == '%' || str[i] == '^' || str[i] == '&' || str[i] == '*' 49 || str[i] == '(' || str[i] == ')' || str[i] == '|' || str[i] == '{' 50 || str[i] == '}' || str[i] == '[' || str[i] == ']' || str[i] == ':' 51 || str[i] == ';' || str[i] == '"' || str[i] == '\'' || str[i] == '' || str[i] == ' ' || str[i] == '/' || str[i] == '?' 53 || str[i] == ' ' || str[i] == ' ' || str[i] == '\t' 54 || str[i] == '~' || str[i] == '`' ){ 55 // printf("String [%s] is not allowed ",str); 56 str[i] ='_'; 57 } //then 58 }//for 59 60 return 1; 61 } //replace_special_character
@barbietripping
@barbietripping Жыл бұрын
@@moth.monster I’m gonna do it accidentally
@matthewrease2376
@matthewrease2376 Жыл бұрын
I think mine looks a bit nicer: echo -ne '\055n'
@mankiewiczm
@mankiewiczm Жыл бұрын
@@matthewrease2376 echo -ne \\0-n is nicer because you see what you are going to echo ;)
@khai96x
@khai96x Жыл бұрын
echo -n -; echo -n n Since you did not forbid the use of 2 echo commands, I'll assume that it's allowed.
@computingthedetails
@computingthedetails Жыл бұрын
Aha! technically yes, I hadn't considered this option, but indeed it is a valid solution :)
@Micetticat
@Micetticat Жыл бұрын
That would also be my solution
@ushiocheng
@ushiocheng Жыл бұрын
oh yeah this is also my first instinct, but somehow this don't work in my environment (zsh 5.8.1 + iTerm on macOS) I think - is a special character in shell?
@Pietro-qz5tm
@Pietro-qz5tm Жыл бұрын
@@ushiocheng if that is the case you can try quoting it. Does echo -n '-'; echo -n n works?
@kopuz.co.uk.
@kopuz.co.uk. Жыл бұрын
echo - -n works
@john.darksoul
@john.darksoul Жыл бұрын
The production quality of small channels nowadays is insane Cool vid mate
@idontfeelsogood2063
@idontfeelsogood2063 Жыл бұрын
I know right? And production quality of big/popular channels nowadays is insane too. But... Insane in the bad way.
@jimschneider799
@jimschneider799 Жыл бұрын
A month late, but... There are several ways to solve the challenge using escape sequences, as interpreted by the bash built-in echo (and the Gnu "coreutils" stand-alone echo), such as: echo -ne '\x2dn' echo -e '\x2dn\c' echo -ne '-\x6e' There are effectively an unlimited number of possibilities, because the '\c' escape tells echo to stop producing output, so anything you add afterwards is ignored. So, I could have done this: echo -e '\x2d\x6e\cwell, isn't this a fine mess? and completely mystified everyone (including myself, in a couple weeks). But for maximum cheese, you can do this: echo() { printf '%s' "$@"; unset echo; } and then the command "echo -n" will print out exactly what's required by the challenge ... once. Okay, I clearly need to stop reading Obfuscated Programming contest entries...
@jimschneider799
@jimschneider799 Жыл бұрын
@@Cosmonaut_Bill - what actually gets output in this case will depend on the output device. Several terminals will, indeed, just echo the characters '-' and 'n'. However, if it's set to raw mode, or if you redirect the output (either via a pipe or directly to a file), the output will consist of the characters dash ('-'), space (' '), backspace ('\b'), and the lowercase letter n.
@calmeilles
@calmeilles Жыл бұрын
echo -e \\x2d\\x6e
@Westtixy
@Westtixy Жыл бұрын
There is another simple way with the carriage return echo -n $' '-n
@majorgnu
@majorgnu Жыл бұрын
I see you found the *extra wrong* kind of answer. The kind that _looks right_ in the terminal. Remember: when in doubt, | hexdump
@majorgnu
@majorgnu Жыл бұрын
echo () { printf "%s " "$@" | head -c -1 ; } In case anyone wants a version that adds a space between arguments, like echo does.
@joachim4660
@joachim4660 Жыл бұрын
Filenames that start with a dash are a problem of its own...
@DavidLindes
@DavidLindes Жыл бұрын
One fairly easily solved, though (in most cases, anyway) by prepending ./ (e.g. ls -l ./-e)
@sdoregor
@sdoregor Жыл бұрын
Yeah that's why I have a file named ‘-i’ in my ‘~/’: that'll possibly stop an accidental ‘rm *’ there.
@DavidLindes
@DavidLindes Жыл бұрын
@@sdoregor hah. Here's hoping... Though, just making the typing of -i as a _habit_ is... a practice I recommend. (I recommend _against_ aliasing it in, though, because then you'll learn to depend on that alias, and one day be on a system where it doesn't exist, and... poof! Much more destructive command than you'd intended!)
@w花b
@w花b Жыл бұрын
User input in a nutshell
@RenderingUser
@RenderingUser Жыл бұрын
0:52 Fish? kitty? You have earned a new subscriber
@Chalisque
@Chalisque Жыл бұрын
The 'broken' bit is really that -- doesn't work as it does with most commands, namely that -- is a switch that indicates that nothing else after it is to be interpreted as a switch. Then echo -- -e would do the right thing. Alas echo -- -e outputs -- -e and not -e But for a quick fix, here's an 11-line C program that outputs its arguments and interprets nothing as a switch: #include int main(int argc, char *argv[]) { for(int i=1; i
@zachb.6179
@zachb.6179 Жыл бұрын
i'm getting the two dashes as part of the output... ~ $ echo -- -e -- -e
@somebodystealsmyname
@somebodystealsmyname Жыл бұрын
@@zachb.6179 That is because the original comment is wrong. If -- would behave like it "should", than echo -- -e would output -e (like printf does).
@1vader
@1vader Жыл бұрын
@@somebodystealsmyname That's exactly what the comment said. It says it should output "-e" but does output "-- -e".
@your_sweetpea
@your_sweetpea Жыл бұрын
Yep! My immediate intuition the whole video was "Yeah, that's why you should use --" but then I tested it in my own shell and it didn't work! Mystifying.
@DavidLindes
@DavidLindes Жыл бұрын
​@@your_sweetpea and OP: yeah, the "real problem" here, in my estimation, is that these things don't use getopt(3) (or getopt_long(3)) for doing their processing. Of course, the other problem is that this is stuff ends up getting relied on, and things start trying to be bug-for-bug compatible... except they often aren't, even.😢
@JoseJoseTHS
@JoseJoseTHS Жыл бұрын
You are creating great content that I know a lot of people will enjoy. Can’t wait to come back here someday when you end up huge
@RenderingUser
@RenderingUser Жыл бұрын
1:43 Really good its not every day you come across a video of such high quality from a channel with..... wait... 34 subscribers????? what??????? you deserve more
@Redditard
@Redditard Жыл бұрын
it's the only reason i subbed to him by just watching his only 1 vid
@infinitelink
@infinitelink Жыл бұрын
He just got 721!
@RenderingUser
@RenderingUser Жыл бұрын
@@infinitelink man Popularity skyrocketed quick
@georgeprout42
@georgeprout42 Жыл бұрын
888 now. I guess that means we can now have subtitles? (For non Brits, or young ones, Teletext page 888 was the subtitles overlay back in the analogue days)
@thefrey9588
@thefrey9588 Жыл бұрын
1.6k now lessgoo
@ovalteen4404
@ovalteen4404 Жыл бұрын
Variable substitution is resolved BEFORE deciding which command to run. This allows you to run a command with a variable that might contain args for that particular command, which is by design. So this is not an echo bug. The only thing you might consider to be an echo bug is that it doesn't bother to interpret the -- sequence.
@brentsaner
@brentsaner Жыл бұрын
Beat me to it.
@Pystro
@Pystro Жыл бұрын
The problem isn't really in the variable substitution. Assume that you don't have a variable because you know that you want to output -e. (You're writing a faq script that prints the arguments one would need to use to achieve certain things or whatever.) The code would be: if [*user wants to know how to get bash to interpret escape sequences*] ;then echo "-e" fi But this still won't work. And it's the fault of the shell's echo function, not any other feature of it, because if you wrote your own echo program that didn't have this bug, the above would work. [edit:] But yes, the "--" not being interpreted is the actual bug here.
@brentsaner
@brentsaner Жыл бұрын
@@Pystro The way it was originally framed was with the switch in a variable. (Which works fine, by the way, with `export v='-e foo' ; echo "${v}"` in bash, which I'm very surprised wasn't mentioned iirc...) If you're rendering a string for help output, you should be using a heredoc anyways.
@randomgeocacher
@randomgeocacher Жыл бұрын
Emitting -whatever but not -e is unreliable behavior. Not implementing - makes the problem worse. I.e. it is bad design that makes code utilizing it bug prone, that’s the point made in the video. It’s not a bug it is terrible design.
@brentsaner
@brentsaner Жыл бұрын
@@randomgeocacher ...You do know it's not just the -e switch. Right? -n is another switch this happens to.
@bazoo513
@bazoo513 Жыл бұрын
This is one of _very few_ YT videos on topics around *ix where this geezer actually learned something very useful. Subscribed!
@krnprsd498
@krnprsd498 Жыл бұрын
I’m new to bash, but not new to escape sequences. Immediately thought of this, and it worked: echo -en “-n \b”
@1creeperbomb
@1creeperbomb Жыл бұрын
"you could be using a superior shell program" *shows fish* zsh for life lol
@_agbl
@_agbl Жыл бұрын
actually you can use escape sequences for print the two bytes a simple solution for this cases is just put the first character in its hexadecimal value, also nice video bro, you got another suscriber
@barjo_
@barjo_ Жыл бұрын
My solution is: echo -e -n\\c The backslash c is used to produce no further output, having it at the very end serves no purpose other than to prevent the -n from being interpreted as a flag. Cool video and fun challenge :)
@Human-ho9bd
@Human-ho9bd 6 ай бұрын
almost had the same solution, i used `echo -n -n\ ` since -n would stop the from working anyways and the would also instantly make the second one non-special
@memetech-
@memetech- Жыл бұрын
“Let me know how good my acting is in the comments” it is good
@nebuladevelopments
@nebuladevelopments Жыл бұрын
Thank you for showing fish when you said superior shell.. I salute you!
@Metruzanca
@Metruzanca Жыл бұрын
Had me laughing at echi -enenenenen. Please do more content like this, especially shell injections like you mentioned.
@dclimenti
@dclimenti Жыл бұрын
Interesting video by the way, First time viewer of you channel but I definitely want to check other videos.
@micropat5341
@micropat5341 Жыл бұрын
I never thought of this bug even though I use echo -e a lot. Of course I have never wanted '-e' or '-n' to be in the output but good to be aware of these potential pitfalls
@metal571
@metal571 Жыл бұрын
Awesome video and really well presented. Excellent channel idea of presenting not so well known details like this, keep it up
@terrior3252
@terrior3252 Жыл бұрын
Interesting seeing you here, are you a mac or linux user?
@metal571
@metal571 Жыл бұрын
@@terrior3252 I am a professional C++ dev for embedded Linux platforms currently
@classicsagat
@classicsagat Жыл бұрын
Hey, this is great, thank you and hope your channel and this video get more love
@etank222
@etank222 Жыл бұрын
8:30 If using a version of echo written by its original authors (both the one true echo and the only sane one) then just echo -n -n will work as expected and provide what you want here, such as the version of echo provided by either plan9port or 9base EDIT: Wanted to add, this specific bug in zipgrep can be fixed by prefixing the variable holding the filename w/a character that isn't -, such as x, and then removing it with sed 's/^x//' on the other end, it has to go thru sed anyway so it's a simple fix. What wouldn't be as simple is dealing with filenames that include newline characters, which I actually don't know if those work or not but my guess would be they don't, but that's a whole different can of worms..
@Gramini
@Gramini Жыл бұрын
My solution to the challenge is a bit less humanly readable than some other solutions in the comments, but it works. echo -n "\x2D\x6E" piping the output to a hex-dumper like hd as a validation shows that it's really only two bytes, no null byte, no new line and no space.
@TheHenrykH
@TheHenrykH Жыл бұрын
Did you mean echo -e "\x2D\x6E"? I am not getting this functionality with -n flag but I am getting it with -e
@AJMansfield1
@AJMansfield1 Жыл бұрын
Solutions to the bash -n challenge: use the "\c" no-further-output escape. $ echo -e "-n\c" Alternately, you can encode either - or n (or both) with either the "\0NNN" octal escape or "\xHH" hexidecimal escape. $ echo -en "-\x6e" $ echo -en "-\0156"
@motyakskellington7723
@motyakskellington7723 Жыл бұрын
best answer
@vblaas246
@vblaas246 Жыл бұрын
@@motyakskellington7723 An added echo -e " " (UNIX end-of-line) or ( ) would be kind, though, for consistency in prompt output. And perhaps consider adding PROMPT_EOL_MARK='' to your .zshrc. See PROMPT_SP .
@majorgnu
@majorgnu Жыл бұрын
For fun I'll add an answer that's _extra wrong._ echo -ne '- -n'
@marianivanov6431
@marianivanov6431 Жыл бұрын
this is my searches whole live. This is an answer for all question about computing. Thank you you are best computer scientist
@scorch855
@scorch855 Жыл бұрын
Rather than giving an actual solution, I will use echo to double down on potentially unexpected behavior you may encounter while working in a terminal. Here is a non-solution which, when printed directly to a terminal, is completely indistinguishable from an actual solution. echo -en '-n \b' Echo transforms the '\b' into its equivalent control character. So when the terminal emulator prints it, it will print the space, but then hit the control character which makes the cursor move one space to the left. Then once it's finished printing, your shell will print your PS1 as usual causing it to overwrite the space character without you ever noticing. You can confirm this by echoing to a file and opening with an editor like vi. Also prints the contents of this file with other programs (like cat) will cause the exact same behavior.
@dmitripogosian5084
@dmitripogosian5084 Жыл бұрын
On my distribution is problem is even mentioned in echo manpages, with a "NOTE: printf(1) is a preferred alternative, which does not have issues outputting option-like strings.
@vlad_cool04
@vlad_cool04 Жыл бұрын
Adding one argument that makes echo to ignore all arguments after it will solve problem
@DeuxisWasTaken
@DeuxisWasTaken Жыл бұрын
"You can use a superior shell" *shows fish*
@dclimenti
@dclimenti Жыл бұрын
You are right. But with the color highlighting in my terminal, hex outputed the backspace in the same color as the background. But I was almost there: bash-5.1$ echo -ne "-n\c" | hex 0x000000: 0x2d 0x6e -n bytes: 2
@stevenchristenson2428
@stevenchristenson2428 Жыл бұрын
This is actually not a bug in bash at all. It is correctly following the implementation of echo that is included with coreutils. If anything this is a bug in zipgrep for using echo instead of the correct printf command. If you do a man echo on a system with coreutils then you notice it has the options for -n -e and -E along with --version and --help. I know someone else posted something similar below but I wanted to clarify this.
@ArmyPig007
@ArmyPig007 Жыл бұрын
There is another solution which you can use to fix every issue caused by argument expansion with echo, the suppression escape sequence "\c". It will prevent everything previous to it from being passed to echo as a toggle. echo -e "-n\c"
@aleksandartyankov1454
@aleksandartyankov1454 Жыл бұрын
awesome video, instantly subscribed
@xGOKOPx
@xGOKOPx Жыл бұрын
Dash doesn't have it's own echo implementation. If you type `which echo` in dash, it will say "/usr/bin/echo". If you want consistent echo behavior across all shells, you can just put `alias echo=/usr/bin/echo` at the beginning of your script; that way the command `echo` will always use the system implementation. I don't actually know why shells implement echo on their own, and why do they do it in incompatible ways too
@denisde4ev
@denisde4ev Жыл бұрын
> Dash does not have echo dash does have echo, "which" command is only build in for zsh and not for bash and dash. Use "type" instead. Executing "type echo" in dash will give "echo is a shell builtin". > why shells implement echo because its simple command and starting child process is a but slow. "time echo" vs "time $(which echo)". but the problem is that its different and in my opinion not simple as in GNU philosophy. my opinion: echo should not take any special options at all and should not interpret special characters, there is already printf command for that. > Using system echo command System echo may also have different implementation that will not be consistent (Mac, BSD, Busybox). Also when using GNU echo will additionally accept special options "--version" and "--help".
@Pengochan
@Pengochan Жыл бұрын
Many programs use '--' (two dashes) to indicate the end of options, specifically so one can use arguments in a command line that look like options.
@puspamadak
@puspamadak Жыл бұрын
One answer to the question is: echo -e "-n\c" The \c after -n will prevent bash from interpreting it as an option. -e option to echo will tell it to interpret \c as an escape sequence. So, output is -n. If you want a newline, put before \c.
@scytube
@scytube Жыл бұрын
Use echo only for simple cases, where you have complete control over its arguments, and printf for everything else. That's the solution, and that's by the way also the solution recommended by POSIX, the overarching standard for "all" Unix-like OSes. It's not that bash's echo is broken, it's that echo is broken _in general_. POSIX phrases this as something like "it's not possible to write cross-implementation compatible echo commands, so just don't". Yeah, you could argue that it's a bug, but it's a bug that's now basically impossible to fix without breaking backwards compatibility, and some of the scripts that rely on one behavior or the other are literally older than most of us.
@glitchy_weasel
@glitchy_weasel Жыл бұрын
What an interesting topIc! Shell scripting is really tricky isn't it, so many corner cases and different behavior depending on the implementation.
@TheSulross
@TheSulross Жыл бұрын
sorry, my bash loyalty remains unshaken, plus I like asking colleagues, "hey, are you Bourne Again?"
@picklypt
@picklypt Жыл бұрын
Amazing video!
@soranuareane
@soranuareane Жыл бұрын
Using echo for escaping... the quote_readline function shows how to do this properly. If you're using a proper shell, use `printf "%q" "the argument"` or, and yes this is a hack, parse the output of `declare -p`. At one point, I wrote my own version of echo in Python that didn't have any of these bugs. Every hyphenated argument was a program argument, and if you wanted to output a program argument, you used --. Moreover, `echo.py -e` would give you an error because I decided that -e expects an argument. I didn't realize echo was this horribly broken on bash, of all things. I knew it was non-portable and I ran into that problem quite a bit when writing code that runs on an older bash on a HP-UX Unix system. Thank you for this video; I learned quite a lot. I've been told to avoid using echo for scripting and only use it for diagnostics and messages, but it's a difficult habit to break.
@TheMAZZTer
@TheMAZZTer Жыл бұрын
So on Linux I would expect adding -- to the command line would cause the command to treat any further arguments as inputs. But echo does not support --! Interesting. I guess it's too late to add it now. Edit: didn't see your comment about it until now. It's also worth noting Windows' echo has a similar issue. echo with no arguments prints the status of the echo state (whether or not commands listed in batch scripts are printed out before being run). the words ON or OFF as arguments toggle the state, and /? displays the help for the command. Fortunately there is a workaround for Windows' issues. If you put a period after the word echo, as opposed to a space, anything you type (including nothing) is echoed back as typed.
@terminally_tired
@terminally_tired Жыл бұрын
5 minutes of slapping my keyboard gave me this result. Works with -e as well. Should mention this was done in zsh echo -n - -n
@allanturner8340
@allanturner8340 Жыл бұрын
There is another player - try /bin/echo that is to say the non shell builtin aka program. If I remember the discussion, during the shell wars when everyone was arguing over which shell was best, the decision was made that bash would mimic /bin/echo. Really not sure if I am remembering right but /bin/echo was made to match another unix. I can't remember which one maybe AT&T, SCO or some other nix?
@Zaydme
@Zaydme Жыл бұрын
You are extremely underrated
@gljames24
@gljames24 Жыл бұрын
Love hearing people tear apart problems in systems that people take for granted. It's how things get fixed!
@DanelonNicolas
@DanelonNicolas Жыл бұрын
even though I saw some JVM in your path I will subscribe to your channel cuz I loved this video! I already trick two friends of mine hahagaah
@kipchickensout
@kipchickensout Жыл бұрын
nice video, I'll stop naming all my files -e now
@soranuareane
@soranuareane Жыл бұрын
Do a video on shell injection like you mentioned. I have cursory knowledge on this, but I could use a refresher and explanation on things I likely forgot since my time in University.
@EgGrox
@EgGrox Жыл бұрын
great vid! subscribed
@MSWS
@MSWS Жыл бұрын
Came across this channel, pretty good! Biggest thing is the mic, seems a bit too close as I can hear a lot of mouth sounds.
@miguelguthridge
@miguelguthridge Жыл бұрын
I think it's also somewhat just a need for a pop filter
@liamkearn
@liamkearn Жыл бұрын
8:15 common fish w. Great video 😁
@peacefulexistence_
@peacefulexistence_ Жыл бұрын
echo -en '\x2d\x6e' satisfies the restrains given. It was actually an interesting exercise, thanks for that ^^
@zperk13
@zperk13 Жыл бұрын
Top tier acting
@S0AndS0
@S0AndS0 Жыл бұрын
For the `sed` usage example `echo` and/or `printf` are not necessary, instead here-doc/string removes the need of piping, eg. ```bash sed ''
@genericyoutubechannel2601
@genericyoutubechannel2601 Жыл бұрын
This was niche and informative enough to earn a subscribe :) I do have one potential counter, though: is the problem really with bash's echo? Or could the problem be with devs not being as thoughtful with their use of echo in programs? Or maybe somewhere in-between?
@richtraube2241
@richtraube2241 Жыл бұрын
Oh no. I gotta edit all my gists now.
@aonodensetsu
@aonodensetsu Жыл бұрын
*echo -en '\x2D\x6E'* is the answer by the way, you just tell echo to interpret the escape sequences as character keycodes for those two characters
@der_Grosse
@der_Grosse Жыл бұрын
Hi, for me working this, cmd: echo -e "\x2D\x6E", output is: -n. In my work I'm using echo command every day in my BASH scripts) Thank you for great video) Greetings from Ukraine!
@widicamdotnet
@widicamdotnet Жыл бұрын
Goodness... I was aware of the switches but always assumed quoting would disarm them... I'll try to remember to stick to printf in future. Interestingly, the echo command in Windows' CMD.EXE is similarly broken - you can't output an empty string, "on" or "off" without weird workarounds.
@WitherBossEntity
@WitherBossEntity Жыл бұрын
My response to debugging bash scripts is to stay away from them as far as possible. Stuff like this, or the madness that is dealing with something as simple as strings with spaces in them (gasp).
@topherfungus8424
@topherfungus8424 Жыл бұрын
Today I learned that you shouldn't name your files "-e"
@motyakskellington7723
@motyakskellington7723 Жыл бұрын
echo -n -- $' '-n the first -n will be interpreted as an option to get rid of the trailing newline -- (double dash) is used to told the program no to consume next arguments as options, unfortunately it will print the double dash but we will remove them later $' ' is used to echo the carriage return character (only one character), this allows to write next bytes over the previous ones (currently double dash) then we simply write -n which will not be interpreted as an option because of the previously written double dash It only prints two characters however there is in fact 6 characters (double dash, space, carriage return, minus, n).
@peacefulexistence_
@peacefulexistence_ Жыл бұрын
POSIX, echo: > ... If the first operand is -n, or if any of the operands contain a backslash ( '\' ) character, the results are implementation-defined. > It is not possible to use echo portably across all POSIX systems unless both -n (as the first argument) and escape sequences are omitted.
@mikeonthecomputer
@mikeonthecomputer Жыл бұрын
Your zipgrep "fix" to use printf instead will still succumb to the same problem the video is about if your have a file named "-v" in the archive. The real trick is to use double hyphen after the printf command to terminate argument parsing. as for the echo challenge: echo -en -n\ (edit: ok, my challenge attempt failed :P)
@computingthedetails
@computingthedetails Жыл бұрын
as far as I can tell, bash only interprets -v as special to printf if it comes before the format string, I just tried with a file called -v and it worked fine.
@mikeonthecomputer
@mikeonthecomputer Жыл бұрын
@@computingthedetails printf may not be a builtin depending on how the bash package was built. Behavior changes on implementation.
@your-mom-irl
@your-mom-irl Жыл бұрын
@@mikeonthecomputer maybe you can just use explicitly /usr/bin/printf.. Or /usr/bin/echo lol
@roelant8069
@roelant8069 Жыл бұрын
My solution to the challenge: echo -n - echo -n n Interesting video by the way, just goes to show how important it is to write good programs that don't have weird exceptions like that. You never know what weird things some user down the line might try to do edit: not to mention, using echo to pass arguments from one script to the other isn't even that weird
Ай бұрын
Bash being clever about adding and removing newlines was already enough to make it really annoying 😂
@markblacket8900
@markblacket8900 Жыл бұрын
nice one, the answer to the challenge is literally on the screen haha
@davidellsworth4203
@davidellsworth4203 Жыл бұрын
The real challenge should have been to output the contents of $VAR, where $VAR may contain anything including just the two-character sequence "-n". That can be done by: echo -e "${VAR/\\/\\\\}\c" This changes all backslashes to double backslashes in what is passed to the *echo* command, then uses "\c" to cut off further output and prevent $VAR from being interpreted as a command-line option to *echo*. Oh, and the real problem with the workaround proposed at 6:37, echo "$VAR ", is that it will cause an extra newline to be outputted if that "invisible" extra space causes the line to wrap, i.e. if $VAR's length is equal to a multiple of the width of the terminal. Also it prevents doing additional output following that echo, because now it won't be properly concatenated, but will have a space before it.
@kubre
@kubre Жыл бұрын
This is the type of CS stuff I want more KZbin. Random details. You deserve way more subs
@Lampe2020
@Lampe2020 Жыл бұрын
bash$ echo -ne "-n \b" -nbash$ # That's my solution. Came up with it in about ten seconds. The space isn't printed because of the \b, which corresponds to the character U+0008 (Backspace) and removes the space but it still counts as invalidating the -n. Okay, when piping the output to hexdump I realized that it's just visual, the bytes coming out are 2D 6E 20 08 (dash lowercase-n space backspace) ...
@natrixnatrix
@natrixnatrix Жыл бұрын
My current favourite shell is actually powershell.
@brynyard
@brynyard Жыл бұрын
The handling of the arguments are definend in the System V reference manual. Apparently the echo implementation (which is a special internal comman in bash, so it doesnt launch a separate proc) is a bit «sloppy».
@jonathancrowder3424
@jonathancrowder3424 Жыл бұрын
When you can't tell if the lump in your skull that's been growing for weeks now is your brain getting bigger, or a tumor from the cancers of tech.
@mechwarrior83
@mechwarrior83 Жыл бұрын
Great quality content for such a tiny channel, soon to blow up no doubt.
@JonWaterfall
@JonWaterfall Жыл бұрын
I see a lot of -e with \c in the comments. I've found that \e works just as well for the purpose of printing "-n" while keeping the newline at the end. echo -e "-n\e" This makes for a bit cleaner output for my own personal preference.
@nerdlife206
@nerdlife206 Жыл бұрын
Dear God... Yeah stuff like this is why I always define the shell that the script is for.
@KerboOnYT
@KerboOnYT Жыл бұрын
This is interesting but I've been using Linux since 1995 and I don't ever recall it being an issue
@TheSpacecraftX
@TheSpacecraftX Жыл бұрын
This is some Windows tier funky behaviour.
@jaqque9633
@jaqque9633 Жыл бұрын
After a bit of playing around, I found the solution most everyone else did: escaping. But I did the bare minimum of escaping: $ echo -ne '\055n' | od -t x1 0000000 2d 6e 0000002 octal ftw (also BASH_VERSION=5.1.4(1)-release for those that want to repeat this in the future, when bash's builtin echo invariably changes. While I agree that there are far better shells out there (zsh) I disagree that it is an aquatic one)
@iliqiliev
@iliqiliev Жыл бұрын
I believe in fish supremacy
@framegrace1
@framegrace1 Жыл бұрын
Having used quite some arcane Unixes in the past, (Various Xenixes/AiXes/HPUxes in the early 80's).... I suspect this is a fossil of how things were back then, and no one even tried to fix from fear of an enormous instant deprecation of milions and milions of small scripts. At that time, the "options" were not treated as a "standard" (Well, today neither... POSIX just defines "conventions") more or less each command did it's thing. At some point they tried to look the same, but the behaviors could still be totally different... Look at "find", "cpio" or "dd" still today....
@bitten2up
@bitten2up Жыл бұрын
once i had a file called -h, yeah it was a pain to remove that file
@knightrider585
@knightrider585 Жыл бұрын
This is a smaller part of the larger set of problems programming in shell script generally. And why I still like perl despite all the haters.
@chotabomjvonychi3485
@chotabomjvonychi3485 Жыл бұрын
Imagine having a friend to shot this kind of videos
@0xGRIDRUNR
@0xGRIDRUNR Жыл бұрын
i think the challenge ended up being a lot easier than it was intended to be. just reading the man page says how to do it (that and including the hex values of the two characters was a BIG hint) it took me just a few minutes to come to SPOILER BELOW echo -ne "\x2d\x6e" edit: forgot the n
@Ether_Void
@Ether_Void Жыл бұрын
I found that adding a \0 also escapes the -n: echo -en "\0-n" echo -en "-\0n" echo -en "-n\0" all work fine, producing only a -n without any characters before or after the -n
@xard64
@xard64 Жыл бұрын
Unfortunately all these add single extra 00 character when examined with hexdump. For example: echo -en "\0-n" |hexdump 0000000 00 2d 6e 0000003
@apmcd47
@apmcd47 Жыл бұрын
Interesting video. Apart from dash, I don't have any of the weird shells you mention (in fact I tend to avoid zsh) but do have ksh93 and the behaviour is of "echo - - -n ..." is identical to bash. I also realised that both these shells (and also /bin/echo - you appear to have forgotten about that one) have interpretation of the backslash turned off by default. You need to turn it on with the -c switch. Given the behaviour of ksh93 echo, bash echo and /bin/echo are the same on my machine (Ubuntu 20.04/focal) I'm wondering if there is some shared source code there? There has always been problematic behaviour with echo (have you seen the old scripts that test for "-n2 vs "\c"?) which is why shell-scriptors are told to use printf over echo in their production code. Challenge: echo -e -n\\c
Жыл бұрын
A bit late, but my solution to the echo -n challenge is: echo -en " \b-n" -e to enable the interpretation of backslash escapes -n to disable the trailing new line character a dummy space at the beginning of the echoed string (could be any character) followed by a backslashed backspace (\b) and finally, the -n characters.
@FreeFireFull
@FreeFireFull Жыл бұрын
Unfortunately that outputs 4 bytes, not 2, so it doesn't really solve the challenge; Both the space and backspace still do get written out
@deeznucz8639
@deeznucz8639 Жыл бұрын
Still better than JavaScript
@GeorgeValkov
@GeorgeValkov Жыл бұрын
echo -e "-n\c" or echo -ne "-n\c" but that breaks /bin/echo which works with -n -n In the past, some packages in OpenWRT failed to build on macOS because /bin/sh echo does not support -e and -n. We patched them with printf.
@tobene
@tobene Жыл бұрын
I actually had a problem that at work and I took me easily a day to find. Some long running setup script always failed because on MacOS "/bin/bash -e" prints "-e" but "bash echo -e" prints nothing
@HypnoGenX
@HypnoGenX Жыл бұрын
echo -en "-n "\\b That was oddly fun to figure out. :-P
@DonAlcohol
@DonAlcohol Жыл бұрын
echo ' -e' same with printf it wont let you print stuff starting with a `-` but there is no harm in adding a whitespace in front of the - , or the $var: printf ' -e' , also works for example with : ARGLIST='-e -u' ; echo " $ARGLIST" ; ps $ARGLIST , note that you put the whitespace with the echo /printf command not with the actual $var, you could also use the echo "${ARGLIST}" without the space wich also works
@Ether_Void
@Ether_Void Жыл бұрын
However printf does properly parse the common "end of arguments" argument "- -"(without space but youtube commends see that as a stying character) so "printf - - -n" works which doesn't work on echo. Also the echo "${ARGLIST}" does not work on bash. That's because echo is not built into bash. So what bash will do is parse the ${ARGLIST} before it calls echo therefor the echo "${ARGLIST}" gets expanded to echo "-n" and the echo gets called. echo can't even see the fact that it get's passed the content of a variable and not a string literal.
@agranero6
@agranero6 7 ай бұрын
This is a non problem, just a little annoyance : you can not escape -n but you can escape it echo -e \0-n pints -n or echo "-n " that also prints -n. The problem only arises if the string begins with - and is a sequence of valid switches and nothing more after very improbable to happen. Just add a \0 before or after and nothing changes, but you need to use -e and quotes.
@0xpatrakar
@0xpatrakar Жыл бұрын
The problems I didn't know I had ☠️
@Susul-lj2wm
@Susul-lj2wm Жыл бұрын
Hooray for escape sequences! echo -en "-\x6e"
@ArthurWolf
@ArthurWolf Жыл бұрын
So, what's the "superior" terminal emulator? He shows some sort of animal, but I didn't recognize it. Anyone know? @Computing: the Details?
echo is broken: a follow-up video
7:14
Computing: the Details
Рет қаралды 11 М.
Bash vs ZSH vs Fish: What's the Difference?
13:32
Eric Murphy
Рет қаралды 162 М.
Became invisible for one day!  #funny #wednesday #memes
00:25
Watch Me
Рет қаралды 57 МЛН
HOW DID HE WIN? 😱
00:33
Topper Guild
Рет қаралды 44 МЛН
Become a bash scripting pro - full course
36:00
CODE IS EVERYTHING
Рет қаралды 45 М.
Why You Shouldn't Nest Your Code
8:30
CodeAesthetic
Рет қаралды 2,6 МЛН
Aider and Claude 3.5: Develop a Full-stack App Without Writing ANY Code!
16:58
Coding the Future With AI
Рет қаралды 18 М.
60 Linux Commands you NEED to know (in 10 minutes)
10:50
NetworkChuck
Рет қаралды 1,4 МЛН
computers suck at division (a painful discovery)
5:09
Low Level Learning
Рет қаралды 1,6 МЛН
Naming Things in Code
7:25
CodeAesthetic
Рет қаралды 2 МЛН
The hidden beauty of the A* algorithm
19:22
polylog
Рет қаралды 844 М.
BASH Environment | Aliases, Functions and Scripts
49:26
Joe Collins
Рет қаралды 89 М.
Transform Your Scripts With Bash Simple Curses
16:15
DistroTube
Рет қаралды 106 М.