Форум русскоязычного сообщества Ubuntu


Следите за новостями русскоязычного сообщества Ubuntu в Twitter-ленте @ubuntu_ru_loco

Автор Тема: Bash-скрипт глобальные и локальные переменные  (Прочитано 2902 раз)

0 Пользователей и 1 Гость просматривают эту тему.

Оффлайн Pingvin1

  • Автор темы
  • Любитель
  • *
  • Сообщений: 81
    • Просмотр профиля
Я собирался написать скрипт для операций с резервной копией, но столкнулся с тем, что значение локальной переменной невозможно передать в глобальную, см.скрипт glob_loc_var.bh: https://cloud.mail.ru/public/SaPK/K7fnrZjm2
Выхлоп скрипта в терминале: https://cloud.mail.ru/public/qi8W/jFpH8gLqq
Как же передать или после окончания цикла обратиться к значению переменной?
Одним Гуглом сыт не будешь Фравия:Искусство поиска

Morisson

  • Гость
Вы думаете кто-то пойдет смотреть Ваш скрипт и выхлоп на облако майл?

Выкладывайте сюда, соответствующим образом оформив.

Оффлайн Pingvin1

  • Автор темы
  • Любитель
  • *
  • Сообщений: 81
    • Просмотр профиля
Выкладывайте сюда, соответствующим образом оформив.
Выхлоп можно и не смотреть, при запуске скрипта он будет таким же.
Сам скрипт по другому как поместить, если с таким расширение прикреплять файл нельзя. Можно с архивировать, то тогда дольше его будет просмотреть.
 
Вообще-то скрипт вот: glob_loc_var.bh:
#!/bin/bash
# cd "~/" # установка текущим любого каталога, Домашнего
declare -i n=2,ng  # определение целых глобальных переменных
ls -1 | while read file # начало цикла: перебор всех файлов и каталогов с пробелами
# ls -1 - отображать один файл на одну строку, -R - рекурсивно отображать содержимое поддиректорий.
do
 let n++ # подсчёт количества файлов и папок в глобальной переменной
 ng=$n # копирование из локальной в глобальную переменную
 echo "Обрабатывается файл или каталог с пробелами: $file"
 echo "\$n= $n \$ng= $ng после подсчёта , -есть счёт в локальной переменной"
done
 echo "Всего файлов и папок=\$n= $n \$ng= $ng , -передачи в глобальную переменную нет"
##  ~/glob_loc_var.bh -строка запуска скрипта, чтобы работал не забыть сделать исполняемым
« Последнее редактирование: 08 Января 2022, 21:56:46 от ALiEN175 »
Одним Гуглом сыт не будешь Фравия:Искусство поиска

Оффлайн ALiEN

  • Администратор
  • Старожил
  • *
  • Сообщений: 6691
  • 20% Cooler
    • Просмотр профиля
1. Не парсите ls!
2. Не нужно никаких определений переменных!
#!/bin/bash
for file in ./* ; do
 n=$((n+1))
 echo "Обрабатывается файл или каталог с пробелами: $file"
done
echo "\$n=$n"

-> Матчасть
-> Неочевидные нюансы
« Последнее редактирование: 08 Января 2022, 22:03:05 от ALiEN175 »
🖥 AsRock B550M Pro4 :: AMD Ryzen 5 3600 :: 16 GB DDR4 :: AMD Radeon RX 6600 :: XFCE
💻 ACER 5750G :: Intel Core i5-2450M :: 6 GB DDR3 :: GeForce GT 630M :: XFCE

Оффлайн valrust

  • Активист
  • *
  • Сообщений: 364
    • Просмотр профиля
В скрипте ошибка в команде declare, должно быть так
declare -i n=2 ngНо это не существенно, так как проблема в другом.

В BASH понятие локальной переменной появляется только при использовании функций. И локальная переменная создается встроенной командой local.
В Вашем скрипте нет функций, поэтому говорить о локальных и глобальных переменных нет смысла.

Но в вашем скрипте есть pipeline (я его переписал в одну строку и убрал комментарии):
ls -1 | while read file ; do let n++ ; ng=$n ; echo "Обрабатывается файл или каталог с пробелами: $file" ; echo "\$n= $n \$ng= $ng после подсчёта , -есть счёт в локальной переменной" ; done
Этот pipeline имеет такую структуру
command1 | command2
где command1 это
ls -1
а command2 это
while read file ; do let n++ ; ng=$n ; echo "Обрабатывается файл или каталог с пробелами: $file" ; echo "\$n= $n \$ng= $ng после подсчёта , -есть счёт в локальной переменной" ; done
Каждая команда, которая участвует в pipeline, запускается в отдельной подоболочке (в отдельном процессе).

В Вашем скрипте цикл while запускается в отдельном (новом) процессе bash. Все переменные, которые используются в цикле, уничтожились после выполнения цикла, так как уничтожился сам процесс в котором он выполнялся.

Поэтому команда
echo "Всего файлов и папок=\$n= $n \$ng= $ng , -передачи в глобальную переменную нет"выдает пустые значения, так как она выполняется в самом первом bashe в котором переменные n и ng никто не менял.
« Последнее редактирование: 11 Января 2022, 02:24:31 от valrust »

Оффлайн Pingvin1

  • Автор темы
  • Любитель
  • *
  • Сообщений: 81
    • Просмотр профиля
-> Матчасть
-> Неочевидные нюансы
Спасибо за ссылки.
Но в вашем скрипте есть pipelien
Спасибо за детальный анализ.
Одним Гуглом сыт не будешь Фравия:Искусство поиска

Оффлайн Pingvin1

  • Автор темы
  • Любитель
  • *
  • Сообщений: 81
    • Просмотр профиля
Неочевидные нюансы
Прочитал по ссылке, что и ls - "Это внешняя команда, выходные данные которой специально предназначены для чтения человеком, а не для парсинга скриптом."
...
"Если вам нужно рекурсивно обработать файлы, то воспользуйтесь UsingFind или присмотритесь к shopt -s globstar в Bash 4 и выше."
Конечно мне нужно рекурсивно отображать содержимое поддиректорий, я жадно дочитал до конца, но примера не нашёл.
> find . -type f -exec some command {} \;  ~15%_Исходного_текста
some command {} \;= Нужно если одна строка (одно совпадение), то переход к следующему файлу иначе сравнение с запомненным совпадающем именем: если да, то вывод пути где имя находится и переход к следующему файлу; если нет, то запоминание совпадающего имени, вывод пути где имя находится и переход к следующему файлу.
"И при этом ваша команда выполнится не только для файлов непосредственно в текущей директории, но и рекурсивно для всех файлов внутри неё."
Задание, проверка и обсуждение открытого кода находится в "Отладка РК вход.zip", распаковываемого в Домашней папке для верных путей: https://cloud.mail.ru/public/t74p/ENrHHxypk
Одним Гуглом сыт не будешь Фравия:Искусство поиска

Оффлайн Pingvin1

  • Автор темы
  • Любитель
  • *
  • Сообщений: 81
    • Просмотр профиля
Я не стал придумывать новую программу, а только внёс изменения подсказанные ALiEN175, valrust и я собирался написать скрипт для операций с резервной копией, но столкнулся с тем, что значение переменной цикла невозможно передать в переменную окружения с помощью export, см.скрипт glob_loc_var.bh:
#!/bin/bash
# cd "~/" # установка текущим любого каталога, в данном случаи Домашнего, тогда не надо указывать путь в ls.
declare -i N=2 NG NUM  # определение целых переменных окружения
ls -R1 "/home/topol/Документы/Linux/Отладка РК/Отладка РК вход" | while read file # начало цикла: перебор всех файлов и каталогов с пробелами
# ls -1 - отображать один файл на одну строку, -R - рекурсивно отображать содержимое поддиректорий.
do
N=$(($N+1)); export N
 export NG=$N # копирование из переменой цикла в переменную окружения
# echo $((NUM+1)) # всегда=1
 if [ -d $file ]; then
   echo "Обрабатывается каталог с пробелами: $file"
 elif [ -f $file ]; then   
   echo "Обрабатывается файл с пробелами: $file"
 else
   echo "Обрабатывается и не файл и не каталог: $file"
 fi
 echo "\$N= $N \$NG= $NG после подсчёта , -есть счёт в переменной цикла"
done
 echo "Всего файлов и папок \$N= $N \$NG= $NG , -передачи в переменные окружения нет"
##  ~/glob_loc_var.bh -строка запуска скрипта, чтобы работал не забыть сделать исполняемым
Я считаю,что нет языка программирования без переменных доступных везде, в Bash-скрипте они называются переменными окружения, но как из цикла передать значения в переменными окружения я не соображу: надежда только на всезнающего All'a.
Одним Гуглом сыт не будешь Фравия:Искусство поиска

Оффлайн ALiEN

  • Администратор
  • Старожил
  • *
  • Сообщений: 6691
  • 20% Cooler
    • Просмотр профиля
#!/bin/bash

DIR="/home/topol/Документы/Linux/Отладка РК/Отладка РК вход"

while read -d $'\0' file ; do
    N=$((N+1))
    if [ -d "$file" ]; then
        echo "Обрабатывается каталог с пробелами: $file"
    elif [ -f "$file" ]; then
        echo "Обрабатывается файл с пробелами: $file"
    else
        echo "Обрабатывается и не файл и не каталог: $file"
    fi
    echo "\$N= $N после подсчёта , -есть счёт в переменной цикла"
done < <(find "$DIR" -print0)

echo "Всего файлов и папок \$N= $N"
« Последнее редактирование: 21 Января 2022, 12:27:23 от ALiEN175 »
🖥 AsRock B550M Pro4 :: AMD Ryzen 5 3600 :: 16 GB DDR4 :: AMD Radeon RX 6600 :: XFCE
💻 ACER 5750G :: Intel Core i5-2450M :: 6 GB DDR3 :: GeForce GT 630M :: XFCE

Оффлайн Pingvin1

  • Автор темы
  • Любитель
  • *
  • Сообщений: 81
    • Просмотр профиля
Работает. СПАСИБО. Разбираюсь.
Одним Гуглом сыт не будешь Фравия:Искусство поиска

Оффлайн Pingvin1

  • Автор темы
  • Любитель
  • *
  • Сообщений: 81
    • Просмотр профиля
Я определил в чём последняя логическая ошибка прочитав перевод рассуждений женщины-программиста: https://habr.com/ru/company/ruvds/blog/503310/
В Ubuntu встроен Python 3, я несколько программ отладил на нём, но при переносе логические ошибки остались бы.
Теперь можно скачать программу на Bash, которая определяет наличие копий названий файлов в каталоге переданным параметром перед созданием резервной копии, спасибо ALiEN175, без него я бы не осилил: https://cloud.mail.ru/public/9MRf/6WxkUWWDF
В Bash через хак возможно сделать многострочные комментарии, что удобно для существенного временного сокращения отлаживаемого кода: https://cgartworld.com/ru/texts/10165-how-to-use-heredoc-in-shell-scripting
« Последнее редактирование: 21 Апреля 2022, 12:09:48 от Pingvin1 »
Одним Гуглом сыт не будешь Фравия:Искусство поиска

 

Страница сгенерирована за 0.03 секунд. Запросов: 25.