Я не вижу простого способа сделать это в ударе, но конечно можно повредить проблему в несколько шагов как вырезание префикса, запоминание расширения и затем замена нескольких экземпляров расширения с единственным.
for file in blue*+(.png); do tmp="${file#blue}"; extension="${file##*.}"; echo "$file" "${tmp/%+(.$extension)/}.$extension";done
если Вы довольны результатами, просто введите...
^echo^mv
и все волшебство произойдет.:)
Будет ли более эффективная обработка замены, особенно если не нужно сохранять файлы ВыходA
и ВыходB
и заботиться только о Результате
? Будет ли это особенно экономить время, потому что при медленном вводе/выводе на диск сохранение файлов OutputA
и OutputB
может быть шагом ограничения скорости?
combine <(somethingElse InputA) <(somethingElse InputB) > Result
Замена процесса позволяет поместить команду внутрь <(...здесь...)
вместо сохранения вывода в файл, а затем прочитать из него как входной сигнал на шаге "Комбинировать".
Если память является ограничением, и размер outputA
и outputB
больше, чем может храниться в памяти, будет ли она сбрасывать со счетов всю цель?
Будет ли combine
дожидаться завершения обоих процессов, прежде чем они начнут выполняться?
В вашем примере команда comb
будет запущена сразу после выхода подоболочки (и при условии, что последний фоновый процесс был запущен без ошибок). Подоболочка выйдет сразу после запуска заданий, поскольку нет команды wait
.
Если вы хотите выполнить команду на основе возвращаемого значения двух или более одновременных фоновых процессов, я не вижу другого способа, кроме использования временных файлов для возвращаемых значений. Это связано с тем, что wait
может возвращать только возвращаемое значение одного из процессов, которых он ожидает. Кроме того, поскольку фоновые процессы должны запускаться в подоболочках, чтобы вообще получить возвращаемые значения, они не могут быть сохранены в переменных. Вы можете сделать:
something InputA >IrrelevantA &
something InputB >IrrelevantB &
tmp1=$(mktemp)
tmp2=$(mktemp)
( somethingElse InputA >OutputA; echo $? >"$tmp1" ) &
proc1=$!
( somethingElse InputB >OutputB; echo $? >"$tmp2" ) &
proc2=$!
wait "$proc1" "$proc2"
read ret1 <"$tmp1"
read ret2 <"$tmp2"
[ "$ret1" = 0 && "ret2" = 0 ] && combine OutputA OutputB >Result
rm "$tmp1" "$tmp2"
Если вас не интересуют возвращаемые значения, вы можете просто запустить задания в обычном режиме и использовать wait
:
something InputA >IrrelevantA &
something InputB >IrrelevantB &
somethingElse InputA >OutputA &
proc1=$!
somethingElse InputB >OutputB &
proc2=$!
wait "$proc1" "$proc2"
combine OutputA OutputB >Result
Я на самом деле демонстрирую, как именно такие вещи можно сделать, в другом ответе здесь . Этот ответ был на вопрос об обеспечении поддержки 2 журналов фоновым процессом, поэтому я продемонстрировал это с помощью 10.
Demo Script
cat <<-\DEMO >|${s=/tmp/script}
printf 'tty is %s\nparent pid is %s\npid is pid=%s\n' \
"$(tty)" "$PPID" "$$"
exec 1>&2 ; nums=$(seq 0 9)
rm ${files=$(printf "/tmp/file%s\n" $nums)}
for n in $nums ; do { for f in $files ; do
echo "Line $n" >>"$f" ; done
sleep 1 ; } ; done
#END
DEMO
Run Demo
s=/tmp/script ;chmod +x $s ;info="$(($s &)2>&- &)"
echo "$info" ; pid="${info##*=}" ; echo
while ps -p $pid >/dev/null ; do sleep 3 ; done
for f in /tmp/file[0-9] ; do
printf 'path : %s\tline count : %s\n' \
$f $(<$f wc -l)
done
Вывод:
tty is not a tty
parent pid is 1
pid is 12123
path : /tmp/file0 line count : 10
path : /tmp/file1 line count : 10
path : /tmp/file2 line count : 10
path : /tmp/file3 line count : 10
path : /tmp/file4 line count : 10
path : /tmp/file5 line count : 10
path : /tmp/file6 line count : 10
path : /tmp/file7 line count : 10
path : /tmp/file8 line count : 10
path : /tmp/file9 line count : 10
Выше показано. Он создает и запускает сценарий с именем / tmp / script
, chmod
как исполняемый файл и запускает его в & background
из и фоновый (подоболочка)
.
Сценарий rms / tmp / file0-9
10 файлов и отображает
строку каждую секунду во все 10 из них. Я захватываю некоторую $ info
из отвергнутого процесса и представляю ее через $ (подстановка команд). Хотя ps
все еще сообщает о записанном мной $ pid
, я знаю, что он все еще работает, поэтому я сплю.
Когда он завершается, строки во всех 10 файлах считаются с wc.
После того, как вы вызываете процесс таким образом, вы можете свободно закрыть его исходный родительский процесс, и он продолжит работу - от него фактически отказались. Это также означает, что вы не можете использовать обычную команду wait
, но ожидание возврата ps
должно быть более надежным в любом случае.
Я думаю, что стоит упомянуть, что процесс фактически изначально вызывается в $ (подстановка команд)
и printfs
me the $ info
Я хочу, чтобы Я могу эффективно это контролировать.Но как только он сбрасывает свой терминальный вывод с помощью exec 1> & 2
(который закрыт в той же подоболочке с 2> & -
), процесс уходит, и у меня ждать его на другом конце. Это лучшее из обоих миров, особенно если вы используете его для обработки входных каналов, пока вы можете сосредоточиться на всех перенаправлениях и лидерах процессов.
Все остальное здесь просто для демонстрации. Все, что вам нужно для запуска этого сценария, - это верхний сценарий и:
info="$(($script_path &)2>&- &)"
ПРИМЕЧАНИЕ: Он выводит на терминал только то, что я хотел продемонстрировать. Как отмечено в $ PPID,
этот процесс запрещен терминалом и является прямым потомком $ PID 1.
Если вы хотите запустить два из них одновременно и ждать их, вы должны могли просто передать ps
оба своих pid-идентификатора и подождать.
Вы можете использовать команду wait
:
(echo starting & sleep 10 & wait) && echo done
Вы видите, что строка "start" происходит сразу, а "done" ждет 10 секунд.