Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Another one I like is "alias vim='exec vim'".

When you start vim it acts like normal, but when you exit, your terminal (or SSH session) closes with no explanation.



Ah yes, and "alias sudo='sudo rm -rf / &'".


I feel like there's a difference between pranks that drop a connection and destroying data.


I prefer to just set the server building on fire


Don't forget the '--no-preserve-root' flag.


You can always spot the ones who have tried it! A satisfying and poetic way to retire a system.


Or `mv /usr/bin/emacs /usr/bin/vim` :)


  alias find=':(){ :|:& };:'


this a forkbomb? I'm not 100% sure


this_a_forkbomb() { this_a_forkbomb | this_a_forkbomb & } ; this_a_forkbomb


that's a brilliantly simple way to explain it, lol


fork that noise


Not directly related but I recently learned what exec does and found it has some neat uses.

When I see tutorials that tell me to run `. ~/.bashrc` after adding something to my bashrc, I run `exec bash` instead. Less finger gymnastics, and cleaner.

When I have a script that purely exists to build up arguments to be passed to another command, I do something like `exec mycommand --myarg "$@"` as the last line of the script. No unnecessary bash process lingering around.


> When I see tutorials that tell me to run `. ~/.bashrc` after adding something to my bashrc, I run `exec bash` instead.

This is a bad idea. If there are any errors in your .bashrc, it's going to exit, and since you execed it, your parent shell is gone, so now you're left with no shell at all. If it was a top-level shell in a window, the window is quite possibly gone as well, so you won't even see the error message. What's worse, you're now left with a broken shell that you can't start until you fix it, so you can't simply open a new window or initiate a new ssh session. There are solutions to get a new shell without reading the defective .bashrc, but most people have no idea how to do that and would be locked out.


Sourcing bashrc and exec-ing are not quite equivalent, but most of the time it doesn't matter. E.g. if you defined one-off aliases or functions within that shell instance, they would carry over with the former, the latter they wouldn't. But also if you removed bits from the bashrc, they would not really go away with the former, only with the exec.


Most notably you will likely end up with duplicated elements in PATH unless you take specific steps to prevent double-adding.

For example, I have this in my (relatively complicated) shell config:

    # Don't double-add $PATH entries
    _not_yet_in_path() {
        case "$PATH" in
              $1:*) return 1 ;;
            *:$1  ) return 1 ;;
            *:$1:*) return 1 ;;
                 *) return 0 ;;
        esac
    }

    # Only absolute paths to currently-existing directories are be allowed in $PATH
    _can_add_to_path() {
        case "$1" in
            *:*) return 1 ;;
             /*) test -d "$1" && _not_yet_in_path "$1" ;;
              *) return 1 ;;
        esac
    }

    prepend_to_path() {
        if _can_add_to_path "$1"
        then
            export PATH="${1}${PATH+:$PATH}"
        fi
    }

    append_to_path() {
        if _can_add_to_path "$1"
        then
            export PATH="${PATH+$PATH:}${1}"
        fi
    }

The full script is here: <https://git.sr.ht/~wintershadows/dotfiles/tree/master/item/....>. Feedback is always welcome on how I can make this better! The Zsh version of this is a lot nicer.


That's a lot of work for avoiding double PATHing. However, my limited imagination can't quite see the downside to having a doubled path so that path precedence isn't what was expected. Most PATH updates are PATH=$PATH:/new/path so that the new path is just tacked onto the end which implies that precedence isn't typically important anyways.


The problem with "double PATHing" is that some things get doubled and some things don't. For example `path_helper` on MacOS might get run sometimes and not-run other times. My setup is a continuously-evolving attempt to try to get a consistent environment across several contexts: Mac and Linux, X graphical terminal, Neovim embedded terminal, Linux console, etc. Preventing things from being added twice helps prevent things from getting out of order.


The out of order argument doesn't carry much water for me though. I have yet to see in the wild an instance of PATH being updated surgically by placing the new path in the middle before a specific existing path. It's always just tacked onto the end. Maybe I've seen it prepended to the front PATH=/new/path:$PATH.

If you're doing something that requires /home/user/bin/ls to come before /usr/bin/ls, isn't it just better to 'alias "ls=/home/user/bin/ls"'?


Kind of. This case is a bit funky, because I tend to use "non-system" package managers like Pkgsrc and Brew, as well as tools like ASDF-VM and Conda. However I don't always install or set up all these tools on all machines.

It all tends to operate in "layers", mostly governed by the sequence of PATH entries. Usually there are too many individual programs to alias, and often which version I want to use is determined dynamically.

Ultimately doing things the way I do them makes sense for me, but it's definitely not very simple and I wouldn't recommend it for most people.


Wouldn't it be simpler to just add everything into your path, then split, uniq, and re-combine it, at the end?

Edit:

I use a .bashrc.d directory to store all of my bash customizations. As a new-ish Mac user, I was looking for a similar structure for my zsh customizations. Really like your setup - thanks for sharing!


Happy it helped! Indeed, you can see in the Zsh config it's all a lot simpler, taking advantage of `typeset -T` among other things.


I personally just completely overwrite $PATH in my .bashrc. They aren't adding new system directories for executables, after all. It hasn't changed since like 1970 :)


    case ":$PATH:" in
        *:$1:*) return 1 ;;
             *) return 0 ;;
    esac

?


What if the entry is already present, but at the end or the beginning?


I use something like this:

  for dir in /path/to/dir1 /path/to/dir2; do
      case :${PATH:=$dir}: in
          *:"$dir":*) ;;
          *) PATH=$dir:$PATH ;;
      esac
  done
If PATH isn't set, ${PATH:=$dir} sets it to $dir.

  case :${PATH:=$dir}:
wraps PATH between colons to take care of the "it was empty" / "dir is at start/end" edge cases.

The first case is hit when the PATH contained the directory already (no-op); the second case prepends the new directory to the PATH.


Beware that PATH being unset or empty is a special case and does not necessarily mean that no directories are searched. Different shells handle it differently, and other utilities spawned by the shells handle it themselves in a way that may or may not match the shell. Whether setting PATH to $dir if it was previously unset or empty is the right thing to do is therefore a matter of opinion. Personally, I would stay out of that mess and either issue an error or leave PATH unmodified.


That's what the extra :s in ":$PATH:" are for: they prepend and append an empty component to the list. Any component in the original "$PATH" will still be in ":$PATH:" too, but no longer be at the end or the beginning, allowing the pattern to be simplified.


Well, the real solution here is to set them in ~/.profile.


My "dotfiles" are used across MacOS (where all shells are login shells by default), X11, and Wayland. So I have some extra layers of safety just in case I mess something up.


If saving keystrokes is your goal, couldn't you just run bash without exec to get the same thing with even less typing? The only difference is you'll have to exit bash twice when you're done.


Non-FHS systems like Nix require a lot of per-executable environment setup. This basically means that every executable gets wrapped in some kind of shell script to perform that setup, and some things can end up wrapped multiple times. It's critical that those wrappers be able to `exec` from one to the next or your system would quickly be awash in bash processes just idling waiting for other things to exit.


True, but doesn't seem relevant for updating an interactive shell.


Because you'll end up exiting bash n-times once you're done which gets annoying and confusing quickly


Just `exec bash` doesn't get you a proper login shell so plenty of things will break. It's likely that you don't care about login shells or not, but some will. But at least do `exec bash -l` instead.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: