Join the discussion

Write your take first — we'll ask for email only when you're ready to publish.

  • Hacker News
  • I wanted something simpler — one consistent way to iterate over anything.

    That's not actually simpler though. Simple is removing everything unnecessary. You took commands which could already do what you wanted, and added an extra program which calls them in specific ways. This will add bugs and maintenance headaches, not be portable, etc. This is added complexity.

    The reason you made this script is not because you wanted simpler, you wanted easier. There's nothing wrong with that, and I'll grant you it probably is, especially for those unaccustomed to these commands. But easier != simpler. Often you'll find that simple is hard and easy is complexity deferred.

  • > Or maybe you pipe into xargs and pray your filenames don’t have spaces…

    Always use -0. Most gnu utilities support it. It makes them put a null byte after every filename instead of a newline. Completely eliminates the problem of dealing with whitespace in the filenames.

  • If you want a shell to interact with the results, you can of course just use a (sub)shell.

        ls -1 ./*.sh | xargs -rd\\n sh -c 'for i in "$@" ; do ... ; done' sh
    
    1. not strictly necessary to use -1 as I believe all common ls detect !isatty(stdout) and produce line-by-line output anyway.

    2. xargs -r just doesn't run the command if there's no input, also not strictly necessary but I'm addicted to using it because it's the sensible default to me.

    3. xargs -d\\n makes it collect fields as full lines, which is what you typically want, unless you're able to generate NULs.

    4. use whatever shell you want of course, but I don't use bashisms, etc., by default, /bin/sh is fine for me, even if it's dash.

    5. the trailing "sh" at the end is due to a quirk of `sh -c` usage, where $0 is the first non option argument, so `printf %s\\n 1 2 3 | xargs -rd\\n sh -c 'for i in "$@" ; do printf "%s " "$i" ; done ; echo'` (note the lack of trailing "sh") would only print "2 3 " as $0 is not included in "$@" ($0 is 1, $1 is 2, $2 is 3). It's very easy to just always give the shell name itself manually as $0 instead of trying to ingest "$0" into your logic.

    Of course, you could `find . -maxdepth 1 -type f -name '*.sh' -print0 | xargs -r0 ...` instead, depending on what you're up to, that may be the easiest. It's definitely the simplest -- as long as your xargs has -0 support.

  • In this thread: bash experts with arcane knowledge, unintentionally demonstrating how awful bash is.

    The obvious solution would be to use something more sane, like PowerShell or nushell, but instead old experts will always defend the skills they have honed for years, while criticizing anything that's different.

  • Not sure I see the point of this. Remembering a bunch of options on one tool is no better than a bunch of tools/constructs? Especially if the latter are useful elsewhere. And it can't be used for scripts unless you start shipping it alongside, which… nah.

    Just go with

      foo | while read X; do bar "$X"; done
  • I lol'd, but do you think this is valid?

    https://github.com/wallach-game/bashumerate/pull/1/files

    to me looks like a right solution, even if I was also tired of writing for loops by hand usually

  • I don’t want to be a downer here, but the structure of this repo and the verbosity+language of the docs feel 80% vibecoded. Not that that’s wrong; I just feel kinda gullible for even clicking on this.

    One uses xargs or parallel only a few times before they remember some of the quirks that but them. And then they become cautious. And then it’s muscle memory. And if it’s not an often occurrence, they learn to check the man page.

    Anyways, in a world of “vibecoding” why add another “tool” to the mix when the LLMs have been trained on all our stackoverflow-posted grievances to begin with?

  • > Consistent syntax — same {} placeholder for files, lines, ranges, or lists

    Inconsistent syntax native bash methods so its an additional syntax to learn.

    > Template mode — single-quoted commands work as shell templates: enumerate -f '*' -- 'cat {} | head -5'

    Passing commands a a single string is BAD. Now you have to think about escaping and quoting. What does {} get replaced with if the enumerant contains unsafe characters? Can it be used as part of a larger argument or only on its own? Who knows, it's not bash. Compared to a bash loop its also always a subshell with all the implications that has - even find can be piped into a normal bash loop.

    > Filters — --include and --exclude with glob patterns

    A fraction of what find or native loops provide. And since this can't replace them in general enumerate is an additional thing to learn on top.

    > Extensible — drop a file in lib/enumerators/ to add custom sources

    To extend bash loops you don't even need root access, you just add the code to the loop.

Explore Birbla archives