0

我知道我可以做类似的事情

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.

4

2 回答 2

2

直接使用命名管道。用于mktemp为每个管道创建临时文件名,以便您可以在完成后删除它们。

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

someOtherCommand "${pipes[@]}"
rm "${pipes[@]}"
于 2018-12-18T20:15:27.557 回答
1

我假设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 分配(让我们避免需要命名管道)。

于 2018-12-18T20:24:49.100 回答