Как я могу использовать строки замены процесса в BASH?

Я знаю, что могу сделать что-то вроде

cat <(cat somefile)

Но я хочу создать строку <(), Так:

for file in *.file; do
    mySubs="${mySubs} <(cat ${file})"
done

cat ${mySubs} #cat <(cat 1.file) <(cat 2.file) ... <(cat something.file)

Без использования eval,

2 ответа

Используйте именованные каналы напрямую. использование mktemp создать временные имена файлов для каждого канала, чтобы вы могли удалить их после завершения.

fifos=()
for f in file1 file2 file3; do
    t=$(mktemp)
    mkfifo "$t"
    pipes+=("$t")
    someCommand "$f" > "$t" &
done

someOtherCommand "${pipes[@]}"
rm "${pipes[@]}"

Я предполагаю, что cat является заменой для более сложной команды. Здесь я явно обертываю это, чтобы показать, что:

#!/usr/bin/env bash

someCommand() { echo "Starting file $1"; cat "$1"; echo "Ending file $1"; }

wrap_all() {

  ## STAGE 1: Assemble the actual command we want to run
  local fd cmd_len retval
  local -a cmd fds fd_args
  cmd_len=$1; shift
  while (( cmd_len > 0 )); do
    cmd+=( "$1" )
    cmd_len=$((cmd_len - 1))
    shift
  done

  ## STAGE 2: Open an instance of someCommand for each remaining argument
  local fd; local -a fds
  fds=( )
  for arg; do
    exec {fd}< <(someCommand "$arg")
    fds+=( "$fd" )
    fd_args+=( "/dev/fd/$fd" )
  done

  ## STAGE 3: Actually run the command
  "${cmd[@]}" "${fd_args[@]}"; retval=$?

  ## STAGE 4: Close all the file descriptors
  for fd in "${fds[@]}"; do
    exec {fd}>&-
  done

  return "$retval"
}

Вызов как:

echo "one" >one.txt; echo "two" >two.txt
wrap_all 1 cat one.txt two.txt

... какие выводы:

Starting file one.txt
one
Ending file one.txt
Starting file two.txt
two
Ending file two.txt

Обратите внимание, что для этого требуется bash 4.1 для поддержки автоматического выделения FD (что позволяет избежать необходимости использования именованных каналов).

Другие вопросы по тегам