Just wanted to share an alias I have in use and found it useful again. It’s a simple wrapper around xargs, which I always forget how to use properly, so I set up an alias for. All it does is operate on each line on stdout.

The arguments are interpreted as the command to execute. The only thing to remember is using the {} as a placeholder for the input line. Look in the examples to understand how its used.

# Pipe each line and execute a command. The "{}" will be replaced by the line.
#
# Example:
#   cat url.txt | foreach echo download {} to directory
#   ls -1 | foreach echo {}
#   find . -maxdepth 2 -type f -name 'M*' | foreach grep "USB" {}
alias foreach='xargs -d "\n" -I{}'

Useful for quickly operating on each line of a file (in example to download from list of urls) or do something with any stdout output line by line. Without remembering or typing a for loop in terminal.

  • Static_Rocket@lemmy.world
    link
    fedilink
    English
    arrow-up
    11
    ·
    9 days ago

    You can also avoid cat since you aren’t actually concatenating files (depending on file size this can be much faster):

    while read -r url; do echo "download $url"; done < urls.txt
    
    • cravl@slrpnk.net
      link
      fedilink
      arrow-up
      1
      ·
      5 days ago

      Pro tip: you can also put the < urls.txt at the start for readability. The arrow doesn’t have to point at the command.

      • Static_Rocket@lemmy.world
        link
        fedilink
        English
        arrow-up
        1
        ·
        5 days ago

        Out of curiosity, how?

        < urls.txt while read -r url; ...
        

        Is a syntax error.

        while read -r url < urls.txt; ...
        

        Result in an infinite loop.

        • cravl@slrpnk.net
          link
          fedilink
          arrow-up
          1
          ·
          17 hours ago

          It’s weird with a multi-command string (i.e. when semicolons get involved), shortest answer is to fiddle with it. I think it may work at the beginning if you put the rest of the command in a (subshell)?