Hacker Newsnew | past | comments | ask | show | jobs | submit | balnaphone's commentslogin

These are part of the rituals of learning how a system works, in the same way interns get tripped up at first when they discover ^S will hang an xterm, until ^Q frees it. If you're aware of the history of it, it makes perfect sense. Unix has a personality, and in this case the kernel needs to decide what executable to run before any shell is involved, so it deliberately avoids the complexity of quoting rules.

I'd give this a try, works with any language:

  #!/usr/bin/env -S "/path/with spaces/my interpreter" --flag1 --flag2
Only if my env didn't have -S support, I might consider a separate launch script like:

  #!/bin/sh
  exec "/path/with spaces/my interpreter" "$0" "$@"
But most decent languages seems to have some way around the issue.

Python

  #!/bin/sh
  """:"
  exec "/path/with spaces/my interpreter" "$0" "$@"
  ":"""
  # Python starts here
  print("ok")
Ruby

  #!/bin/sh
  exec "/path/with spaces/ruby" -x "$0" "$@"
  #!ruby
  puts "ok"
Node.js

  #!/bin/sh
  /* 2>/dev/null
  exec "/path/with spaces/node" "$0" "$@"
  */
  console.log("ok");
Perl

  #!/bin/sh
  exec "/path/with spaces/perl" -x "$0" "$@"
  #!perl
  print "ok\n";
Common Lisp (SBCL) / Scheme (e.g. Guile)

  #!/bin/sh
  #|
  exec "/path/with spaces/sbcl" --script "$0" "$@"
  |#
  (format t "ok~%")
C

  #!/bin/sh
  #if 0
  exec "/path/with spaces/tcc" -run "$0" "$@"
  #endif
  
  #include <stdio.h>
  
  int main(int argc, char **argv)
  {
      puts("ok");
      return 0;
  }
Racket

  #!/bin/sh
  #|
  exec "/path/with spaces/racket" "$0" "$@"
  |#
  #lang racket
  (displayln "ok")
Haskell

  #!/bin/sh
  #if 0
  exec "/path/with spaces/runghc" -cpp "$0" "$@"
  #endif
  
  main :: IO ()
  main = putStrLn "ok"
Ocaml (needs bash process substitution)

  #!/usr/bin/env bash
  exec "/path/with spaces/ocaml" -no-version /dev/fd/3 "$@" 3< <(tail -n +3 "$0")
  print_endline "ok";;


> I'd give this a try, works with any language:

  #!/usr/bin/env -S "/path/with spaces/my interpreter" --flag1 --flag2
This won't do what you're thinking it does. If I run that, I get:

  env: No terminating quote for string: /path/with"/path/with
… because the string you've given env -S on my system is malformed, and lacks a terminating quote. (You can test this w/ just giving an unterminated quoted string to env … I have no idea why the messaging is so funky looking, but that's sort of par for the course here.)

As I alluded to in my post, shebangs don't handle escaping. Now, yes, you're thinking that env will do it, here. The other problem with shebangs is that they're ridiculously unstandardized. On Linux, for example, that shebang will parse out to:

  #!/usr/bin/env -S "/path/with spaces/my interpreter" --flag1 --flag2

  argv[0]: "/usr/bin/env"
  argv[1]: "-S"
  argv[2]: "\"/path/with spaces/my interpreter\" --flag1 --flag2"
  argv[3]: <script filename>
& then -S proceeds as you expect it to. Things appear to work.

On my system,

  #!/usr/bin/env -S "/path/with spaces/my interpreter" --flag1 --flag2

  argv[0]: "/usr/bin/env"
  argv[1]: "-S"
  argv[2]: "\"/path/with"
  argv[3]: "spaces/my"
  argv[4]: "interpreter"
  argv[5]: "--flag1"
  argv[6]: "--flag2"
  argv[7]: <script filename>
This is because Linux passes everything after the first space as a single arg. macOS splits on spaces, but does no further processing (such as some form of backslash escapes) beyond that.

Since,

  env -S '"/path/with' <other args…>
is nonsense, env errors out with the above error.


It works fine with GNU env with -S support, and a GNU-compatible kernel. I'm aware that won't work on some other systems, hence the 9 other examples. I said I would try that first and see how it goes, and low and behold it works fine on the systems I use.

  $ cat bbb.ml 
  #!/usr/bin/env -S "/home/user/.local/bin/o c a m l" -no-version
  print_endline "ok";;
  $ ls -lh ~/.local/bin/"o c a m l"
  lrwxrwxrwx 1 user user 14 Feb 27 07:26 '/home/user/.local/bin/o c a m l' -> /usr/bin/ocaml
  $ chmod a+rx bbb.ml
  $ ./bbb.ml
  ok
  $ 
But if it didn't work, you can get pretty good mileage out of abusing sh to get the job done for many popular languages.


When you say "just... run linux", are you referring to termux, or something else ? How do you run a linux userspace in Android ?


I mean a fully fledged regular debian

https://www.linuxjournal.com/content/bringing-desktop-linux-...

https://source.android.com/docs/whatsnew/android-16-release#...

While this is mostly a KVM setup, there's nothing specific about Android that prevents a linux userspace from running in there. Each app is almost one already. Most of its core components have been integrated into linux's main repository (like binder), and AOSP isn't that far off from a regular Linux. Sure, zygote, user & power management are not exactly a standard install, but they're not that crazy either


Okay, so suppose I want a linux and not an android phone, so I get an android phone, disable login password etc, and delete everything except "Linux Terminal" and put my linux there.

What sort of tradeoffs would I see? Performance? Battery life? Security (secure enclave access?)


That’s all very convincing. For users who just want a Linux phone? Not there yet. Android or not.


Aside from a misplaced obstination to have _Linux_ as the base for your phone with all the awful power management, high energy use, bad governors, terrible process isolation and fleeing security holes everywhere in a phone that most of the times contains access to your entire life, what does Linux give you that Android doesn't? Both are FOSS.


This exists, just use https://github.com/sigoden/aichat with local ollama and a model like qwen2.5-coder:7b or better (e.g. gemma3:12b).

Add this to ~/.bashrc :

    # bind Alt-e on the command line to replace text with command
    _aichat_bash() {
        if [[ -n "$READLINE_LINE" ]]; then
            READLINE_LINE=$(aichat -e "$READLINE_LINE")
            READLINE_POINT=${#READLINE_LINE}
        fi
    }
    bind -x '"\ee": _aichat_bash'
In the example you gave i get:

    find . -type f -name "*.mp4" -exec ffmpeg -i {} -c:v libaom-av1 -crf 30 -b:v 0 -c:a copy ~/Videos/{}.mkv \;
But if you don't like that you can press Ctrl-Shift-_ (bash has emacs keybindings) to undo and try something else. You can also put a # mark in front and hit enter, then up arrow then Alt-e so you know what created the command.




Perhaps that is inexcusable. GNU gcc version 13.2.0 (with -O2, as documented) does report a problem.

    $ cat tst.c
    int main () {
      int x[10];
      return *(x+20);
    }
    $ gcc -Wall -O2 tst.c
    tst.c: In function ‘main’:
    tst.c:3:10: warning: array subscript 20 is outside array bounds of ‘int[10]’ [-Warray-bounds=]
        3 |   return *(x+20);
          |          ^~~~~~~
    tst.c:2:7: note: at offset 80 into object ‘x’ of size 40
        2 |   int x[10];
          |       ^


These are easy mode arrays, with size and offset known at compile time. Receiving x as an int* parameter to a function, with no way to know its length automatically, would be more realistic.


I would save my data in CSV format, then use this. Save the code below as chunk.pl (remove leading spaces) and call it as "perl chunk.pl" :

    #!/usr/bin/perl -CSD -w -Mstrict -Mwarnings -MText::CSV
    
    # chunk.pl -- split csv files into chunks
    
    # Usage message and exit if needed
    if (!@ARGV || $ARGV[0] eq '-h') {
        print "Usage: $0 input_csv [chunk_size] [output_filename_format] [separator]\n";
        print "Example: $0 input.csv 500 'input-%08d.csv' ','\n";
        exit;
    }
    
    # Set command-line arguments
    my ($INFILE, $CHUNKSIZE, $FMT, $SEP) = @ARGV;
    $CHUNKSIZE //= 500;
    $FMT //= "data-%08d.csv";
    $SEP //= ",";
    
    # Initialize CSV, file handles, and counters
    my $csv = Text::CSV->new({ binary => 1, auto_diag => 1, sep_char => $SEP, eol => "\n" });
    my ($i, $f, $out) = (0, 1, undef);
    open my $in, "<:encoding(UTF-8)", $INFILE or die "Cannot open $INFILE: $!";
    
    # Main loop
    while (my $row = $csv->getline($in)) {
        if ($i % $CHUNKSIZE == 0) {
            close $out if defined $out;
            open $out, ">:encoding(UTF-8)", sprintf($FMT, $f++) or die "Cannot open output file: $!";
        }
        $csv->print($out, $row) or die "Failed to write row: $!";
        $i++;
    }
    
    # Clean up: close file handles
    close $out if defined $out;
    close $in;


I suppose R might be a better choice...

    library(readr)
    library(dplyr)
    library(purrr)
    data <- read_csv("input.csv")
    chunk_size <- 500
    chunks <- split(data, ceiling(seq_along(1:nrow(data))/chunk_size))
    iwalk(chunks, ~write_csv(.x, sprintf("data-%04d.csv", .y)))


Can you post your tmux config that mocks GNU Screen?

Here is mine : https://pastebin.com/ZVWYcpyU , but a lot of GNU Screen muscle memory fails for various reasons.

The main reasons I'm trying to switch are: better scrollback support, and better mouse support (both for tmux itself and for pass-through to terminal applications). Having used GNU Screen for 32 years, it's difficult for me to even think about what keys I'm hitting, it's below the level of conscious recognition at this point.


Here is mine - it's pretty short. I think it reflects what I use and don't use, so I'm not sure it's useful to you!

    # remap prefix from 'C-b' to 'C-a'
    unbind C-b
    set-option -g prefix C-a
    bind-key a send-prefix
    bind-key C-n next-window
    bind-key C-p previous-window
    
    unbind C-a
    bind C-a last-window
    
    unbind A
    # Default C-a ,
    bind A command-prompt -I "#W" "rename-window '%%'"
    unbind k
    bind k confirm-before "kill-window"
    
    bind Escape copy-mode
    
    # start counting from 1
    set -g base-index 1
    setw -g pane-base-index 1
    
    # vi keys scrollback
    setw -g mode-keys vi
    
    # Style
    set -g status-bg black
    set -g status-fg white
    
    # Make current tab visible
    setw -g window-status-current-format "#[reverse]*#I:#W*"


The site doesn't scroll at all on Firefox(X11) with ublock and umatrix, even when the non-tracking sites are enabled. In Brave browser it somewhat works in a janky way, but given that the site apparently brings a 24-core threadripper with 128GB RAM to it's knees, it certainly doesn't inspire confidence in the product, which otherwise looks pretty good.


Steve Mann resolved this notational dilemma by using the term "crown", as in binary = crown 1, octal = crown 7, decimal = crown 9, hex = crown F, and so on.


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

Search: