Edit: SOLVED. Thank you all for your incredible insights! All of you helped me improve my code and knowledge! Special thanks to @Quibblekrust@thelemmy.club who just NAILED it. :)

I’m playing around with Bash just to learn.

LIST=$(ls); for i in $LIST; do echo "I found one!"; done

The variable “i” could literally be anything, as long as it doesn’t have a special meaning for Bash, in which case I’d have to escape it, right? Anyway, my real question is: how does do (or rather the whole for-expression) know that “i” here means “for every line/item that ls outputs”? The above one liner works great and writes “I found one!” the number of times corresponding to the number of lines or items that ls outputs. But I would like to understand why it worked…

I’m a complete beginner at both Bash and C, but I understand some basic concepts.

  • rycee@lemmy.world
    link
    fedilink
    arrow-up
    3
    ·
    4 days ago

    Wouldn’t for i in "$LIST"; just result in a single loop iteration with $i being the entirety of $LIST?

    • harsh3466@lemmy.ml
      link
      fedilink
      arrow-up
      4
      ·
      4 days ago

      It would not, as @Quibblekrust@thelemmy.club explained in their comment (which I neglected to include in my explanation), Bash uses a special variable called IFS when executing for loops like this. IFS stands for Input Field Separators, and is a list of one of each type of whitespace (tab, space, and newline), and uses these as separators automatically.

      So instead of taking that whole ls output as one string of text, the for loop automatically separates it into an iterable list of strings using the newline separator.

      • rycee@lemmy.world
        link
        fedilink
        arrow-up
        6
        ·
        4 days ago

        I’m pretty sure that IFS does not apply to quoted strings since word splitting happens before the quote removal (see Shell Expansion).

        $ ( files=$(ls); IFS=$'\n' ; for x in $files; do echo $x; done )
        file a.txt
        file b.txt
        plainfile.txt
        
        $ ( files=$(ls); IFS=$'\n' ; for x in "$files"; do echo $x; done )
        file a.txt file b.txt plainfile.txt
        
      • frongt@lemmy.zip
        link
        fedilink
        arrow-up
        2
        ·
        4 days ago

        Which makes it real fun when you have spaces in filenames!

        Really you shouldn’t use ls as input to for. Use find -exec or something.