#bash
#bash
Вопрос:
У меня есть следующий скрипт, и я хочу перезаписать progress
переменную значением из цикла, но я изо всех сил пытаюсь заставить это работать. Я прочитал много потоков, но все они, похоже, предлагают что-то вроде записи для вывода в файл, а затем снова считывают его, но я не хочу этого делать.
#!/bin/bash
function Upload {
find . -type f -name "*.test" -printf "%fn"| sort -k1 | while read fname; do
progressBar=$(echo "scale=2 ; $progress $percentage" | bc)
echo "bar: $progressBar"
progress=$progressBar
done
}
progress=0
totalFiles=$(find . -name "*.test" | wc -l)
totalCalc=$(($totalFiles 1))
percentage=$(echo "scale=2 ; 100 / $totalCalc" | bc)
Upload
echo $progress
Как я могу получить переменную вне цикла / подоболочки и перезаписать основную переменную?
Комментарии:
1. Помимо решения, изложенного в моем ответе, вы также можете написать свою программу, скажем, на Perl, Python или Ruby, где у вас есть все в одном процессе.
progressBar
Тогда ваша будет просто глобальной переменной.
Ответ №1:
Как вы уже правильно указали в своем вопросе, вы запускаете тело цикла в дочернем процессе, поэтому, даже если вы экспортируете переменную, изменение не может быть замечено в родительском процессе.
Запись в файл is и извлечение его в вашей «основной» программе легко, если вы делаете это правильно:
В вашей основной программе (перед вызовом вашей функции) настройте файл следующим образом:
export progressBarFile=/tmp/progressBar.$
Это гарантирует, что несколько процессов вашего скрипта используют для этого свой собственный файл.
В вашем цикле выполните
echo $progressBar >$progressBarFile
Затем, после выполнения вашей функции, извлеките значение с помощью
progressBar=$(<$progressBarFile)
В конце концов, вы можете удалить этот файл следующим образом:
rm $progressBarFile
Если вы действительно боитесь, что у вас останется временный файл, вы можете использовать trap
его для преждевременного прерывания вашего скрипта и удаления файла внутри функции trap .
Другой возможностью (без использования файла) было бы использование массива:
files=( $(find . -type f -name "*.test" -printf "%fn"| sort -k1) )
for fname in "${files[@]}"
do
...
done
В этом случае тело вашего цикла не является дочерним процессом.
Комментарии:
1. Спасибо за объяснение. Причина, по которой я хочу избежать записи во внешний файл, заключается в том, что в реальном скрипте я записываю прогресс в базу данных mysql, чтобы моя веб-страница могла считывать прогресс из нее. Я подумал, что если это невозможно сделать без сохранения переменной вне скрипта, я мог бы также извлечь ее из своей базы данных. Я не программист и не учусь, пока работаю над этим, поэтому я предпочитаю не добавлять в микс другой язык программирования.
2. @sjaak: Так, может быть, вы можете использовать мое второе предложение (используя массив, чтобы избежать дочернего процесса)?