A wildcard that executes a command once for each match

Alternative name: like loop without loop or xargs.

I recently switched to zsh due to its many features. I am curious: is there a function that extends wildcards so that the command is executed once for each match, and not just once for all matches at once.

Example

The command ebook-convert input_file output_file [options]accepts only one input file. When I want to convert several files, I have to execute the command several times manually or use a loop, for example:

for i in *.epub; do 
    ebook-convert "$i" .mobi
done

What I need is a template that works like a loop, so that I can save a few keystrokes. Let the specified wildcard . Team

ebook-convert.epub .mobi

should expand to

ebook-convert 1stMatch.epub .mobi
ebook-convert 2ndMatch.epub .mobi
ebook-convert 3rdMatch.epub .mobi
...

, ( ). , , , , zsh .

+4
4

, ,

ebook-convert *.epub .mobi

... , - . ? , - :

  • ; done
  • Ctrl A,
  • type for i in...
  • ....

readline:

readline commands :

end-of-line                    # (start from the end for consistency)
; done                         # type in the loop closing statement
character-search-backward *    # go back to the where the glob is
shell-backward-word            # (in case the glob is in the mid-word)
shell-kill-word                # "cut" the word with the glob
beginning-of-line              # go back to the start of the line
for i in                       # type the beginning of the loop opening
yank                           # "paste" the word with the glob
; do                           # type the end of the loop opening

:

readline, , , . , .

, . , \C-eend-of-line.

bind '"\eB": shell-backward-word'
bind '"\eD": shell-kill-word'

bind '"\C-i": "\C-e; done\e\C-]*\eB\eD \"$i\"\C-afor i in\C-y; do "'

inputrc .

:

:

  • -

    ebook-convert *.epub .mobi
  • Ctrl I
  • for i in *.epub; do ebook-convert "$i" .mobi; done

, , \C-j , accept-line ( , Return).

+3

zargs zsh.

GNU xargs. , ,

zshcontrib(1): OTHER FUNCTIONS, zargs

, :

autoload -Uz zargs
zargs -I⁂ -- *.epub -- ebook-convert ⁂ .mobi

PS: zmv, .

+3

for , :

for f (*.epub) ebook-convert $f .mobi
+1

script, :

#!/bin/bash

command="$1"
shift
if
  [[ $# -lt 3 ]]
then
  echo "Usage: command file/blog arg1, arg2..."
  exit 1
fi

declare -a files=()
while [ "$1" != "--" ]
do
  [ "$1" ] || continue
  files+=("$1")
  shift
done

if
  [ "$1" != "--" ]
then
  echo "Separator not found : end file list with --"
  exit 1
fi
shift

for file in "${files[@]}"
do
  "$command" "$file" "$@"
done

(, script apply_to).

apply_to command /dir/* arg1, arg2...

, .

0

Source: https://habr.com/ru/post/1668773/


All Articles