Как я могу использовать строки замены процесса в 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 (что позволяет избежать необходимости использования именованных каналов).