1
0
Fork 0

2024-09-30

This commit is contained in:
Gennadiy 2024-10-01 18:02:31 +03:00
parent ccb23ae867
commit 6fb4dfdbf4
9 changed files with 56 additions and 59 deletions

View file

@ -1,5 +1,5 @@
| Незавершённые публикации | Язык | Обновление | | Незавершённые публикации | Язык | Обновление |
|:-----------------------------------------------------------------|------|------------| |------------------------------------------------------------------|------|------------|
| [Распараллеливание скриптов Bash](parallelizing-bash-scripts.md) | Bash | 2024.08.15 | | [Распараллеливание скриптов Bash](parallelizing-bash-scripts.md) | Bash | 2024.09.05 |
| [Циклический алгоритм распределения задач](round-robin.md) | Java | 2023.06.05 | | [Циклический алгоритм распределения задач](round-robin.md) | Java | 2023.06.05 |

View file

@ -1,13 +1,12 @@
# Распараллеливание скриптов Bash # Распараллеливание скриптов Bash
Примером последовательности действий, не зависящих друг от друга, могут быть — итерации циклов, или вызовы функций с Рассмотрим последовательность действий, не зависящих друг от друга — это итерации циклов, или вызовы функций с параметрами.
параметрами. Когда цикл один, или функция одна — это тривиальная задача для распараллеливания. Рассмотрим усложнённую Когда цикл один, или функция одна — это тривиальная задача для распараллеливания. Рассмотрим усложнённую модель с тремя
модель с тремя функциями и тремя параметрами для каждой — будем распараллеливать вызовы этих функций. функциями и тремя параметрами для каждой — будем распараллеливать вызовы этих функций с использованием программы `xargs`.
Сначала кодируем параметры в HEX коды и отбрасываем разделители строк — чтобы не заниматься экранированием спецсимволов. Для решения вопроса об экранировании спецсимволов — сначала все параметры кодируем в HEX коды и после этого составляем с ними
Затем создаём массив строк — вызовы функций с параметрами. Далее выполняем эти строки в параллельном режиме с помощью строки — вызовы функций с параметрами. Далее обходим массив строк и выполняем функции в параллельном режиме. Внутри каждой из
программы `xargs` — вызываем целевые функции командой `eval`. Внутри каждой функции сначала декодируем параметры них сначала декодируем параметры обратно и затем работаем с ними. Для наглядности замеряем общее время выполнения функций.
обратно и затем работаем с ними. Дополнительно для наглядности замеряем общее время выполнения функций.
```bash ```bash
#!/bin/bash #!/bin/bash
@ -41,10 +40,10 @@ function third_func {
#---------------------------------------------------------------------------; #---------------------------------------------------------------------------;
# вспомогательные функции и экспорт для дочерних процессов # вспомогательные функции и экспорт для дочерних процессов
#---------------------------------------------------------------------------; #---------------------------------------------------------------------------;
# удаление разделителей строк и кодирование символов в HEX коды # кодирование символов в HEX коды [U0000-UFFFF]
function encode { echo "$1" | tr -d '\r\n' | uni2ascii -aE -qps; } function encode { echo "$1" | uni2ascii -aE -qps; }
# декодирование символов из HEX кодов и удаление разделителей строк # декодирование символов из HEX кодов [U0000-UFFFF]
function decode { echo "$1" | ascii2uni -aE -q | tr -d '\r\n'; } function decode { echo "$1" | ascii2uni -aE -q; }
# перечисление используемых функций в дочерних процессах bash # перечисление используемых функций в дочерних процессах bash
export -f decode first_func second_func third_func export -f decode first_func second_func third_func
#---------------------------------------------------------------------------; #---------------------------------------------------------------------------;
@ -60,33 +59,33 @@ p1="$(encode "$param1")"
p2="$(encode "$param2")" p2="$(encode "$param2")"
# массив строк — вызовы функций с параметрами # массив строк — вызовы функций с параметрами
array[0]="first_func '$p0' '$p1' '$p2'" array[0]="first_func '$p0' '$p1' '$p2'"
array[1]="second_func '$p2' '$p0' '$p1'" array[1]="second_func '$p1' '$p2' '$p0'"
array[2]="third_func '$p1' '$p2' '$p0'" array[2]="third_func '$p2' '$p0' '$p1'"
# вывод строк массива для наглядности # вывод строк массива для наглядности
printf '%s\n' "${array[@]}" printf '%s\n' "${array[@]}"
#---------------------------------------------------------------------------; #---------------------------------------------------------------------------;
# параллельный вызов функций и замер общего времени выполнения # параллельное выполнение функций и замер общего времени выполнения
#---------------------------------------------------------------------------; #---------------------------------------------------------------------------;
# текущее время в миллисекундах # текущее время в миллисекундах
time_ms="$(date '+%s%3N')" time_ms="$(date '+%s%3N')"
# вывод строк массива и вызов функции для каждой из них в параллельном режиме # вывод строк массива и вызов функции для каждой из них в параллельном режиме
printf '%s\0' "${array[@]}" | xargs -I{} -n1 -0 -P0 bash -c 'eval "{}"' printf '%s\0' "${array[@]}" | xargs -I{} -n1 -0 -P0 bash -c "{}"
# время работы в миллисекундах # время работы в миллисекундах
echo "Общее время выполнения: $(("$(date '+%s%3N')" - "$time_ms")) мс." echo "Общее время выполнения: $(("$(date '+%s%3N')" - "$time_ms")) мс."
``` ```
## Вывод ## Вывод
Строки массива, вызовы функций с параметрами через пробелы в кавычках Строки массива вызовы функций с параметрами через пробелы в кавычках
``` ```
first_func 'U0020U0024U0070U0061U0072U0061U006DU0022' '' 'U0022U0024U0032U0022U0021U003DU0022U0024U0031U0022' first_func 'U0020U0024U0070U0061U0072U0061U006DU0022' '' 'U0022U0024U0032U0022U0021U003DU0022U0024U0031U0022'
second_func 'U0022U0024U0032U0022U0021U003DU0022U0024U0031U0022' 'U0020U0024U0070U0061U0072U0061U006DU0022' '' second_func '' 'U0022U0024U0032U0022U0021U003DU0022U0024U0031U0022' 'U0020U0024U0070U0061U0072U0061U006DU0022'
third_func '' 'U0022U0024U0032U0022U0021U003DU0022U0024U0031U0022' 'U0020U0024U0070U0061U0072U0061U006DU0022' third_func 'U0022U0024U0032U0022U0021U003DU0022U0024U0031U0022' 'U0020U0024U0070U0061U0072U0061U006DU0022' ''
``` ```
Параллельная работа функций, порядок может изменяться Параллельная работа функций, порядок может изменяться
``` ```
3 third_func [] ["$2"!="$1"] [ $param"] 3 third_func ["$2"!="$1"] [ $param"] []
2 second_func ["$2"!="$1"] [ $param"] [] 2 second_func [] ["$2"!="$1"] [ $param"]
1 first_func [ $param"] [] ["$2"!="$1"] 1 first_func [ $param"] [] ["$2"!="$1"]
``` ```
Время работы функций в миллисекундах Время работы функций в миллисекундах

View file

@ -1,5 +1,5 @@
#!/bin/bash #!/bin/bash
#remote="gitea.com" #domain="gitea.com"
remote="git.org.ru" domain="git.org.ru"
#remote="hub.mos.ru" #domain="hub.mos.ru"
echo "Переключение домена удалённого репозитория: $remote" echo "Переключение домена удалённого репозитория: $domain"

View file

@ -1,13 +1,11 @@
#!/bin/bash #!/bin/bash
echo "Обновление домена удалённого репозитория в перекрёстных ссылках в описаниях." echo "Обновление домена удалённого репозитория в перекрёстных ссылках в описаниях."
export remote="git.org.ru" && source info_param.sh export domain="git.org.ru" && source info_param.sh
# экранируем точки в названии домена
export domain="${remote//"."/"\."}"
# название домена в верхнем регистре # название домена в верхнем регистре
export DOMAIN="${domain^^}" export DOMAIN="${domain^^}"
# обработка информационных файлов # обработка информационных файлов
function references { function references {
echo "$remote => $1" echo "$domain => $1"
# сбрасываем значения параметров # сбрасываем значения параметров
sed -i "s|gitea\.com|tmp_stub|g" "$1" sed -i "s|gitea\.com|tmp_stub|g" "$1"
sed -i "s|GITEA\.COM|TMP_STUB|g" "$1" sed -i "s|GITEA\.COM|TMP_STUB|g" "$1"
@ -18,7 +16,7 @@ function references {
# устанавливаем значения параметров # устанавливаем значения параметров
sed -i "s|tmp_stub|$domain|g" "$1" sed -i "s|tmp_stub|$domain|g" "$1"
sed -i "s|TMP_STUB|$DOMAIN|g" "$1" sed -i "s|TMP_STUB|$DOMAIN|g" "$1"
if [ "$remote" == "hub.mos.ru" ]; then if [ "$domain" == "hub.mos.ru" ]; then
sed -i "s|src/branch|blob|g" "$1" sed -i "s|src/branch|blob|g" "$1"
else else
sed -i "s|blob|src/branch|g" "$1" sed -i "s|blob|src/branch|g" "$1"

View file

@ -23,14 +23,14 @@ function directory_tree {
if [ -d "$path" ]; then if [ -d "$path" ]; then
local list # массив файлов и каталогов local list # массив файлов и каталогов
readarray -t list <<<"$(list_directory_contents "$path")" readarray -t list <<<"$(list_directory_contents "$path")"
local len=${#list[@]} # размер массива local size=${#list[@]} # длина массива
local i # счётчик local i # счётчик
for ((i = 0; i < len; i++)); do for ((i = 0; i < size; i++)); do
if [ -z "${list[$i]}" ]; then if [ -z "${list[$i]}" ]; then
continue # пропустить пустой каталог continue # пропустить пустой каталог
elif ((len == 1)); then elif ((size == 1)); then
directory_tree "$path/${list[$i]}" "$tail" "$tail" "one" directory_tree "$path/${list[$i]}" "$tail" "$tail" "one"
elif ((i < len - 1)); then elif ((i < size - 1)); then
directory_tree "$path/${list[$i]}" "$tail├─ " "$tail" directory_tree "$path/${list[$i]}" "$tail├─ " "$tail"
else else
directory_tree "$path/${list[$i]}" "$tail└─ " "$tail " directory_tree "$path/${list[$i]}" "$tail└─ " "$tail "

View file

@ -1,6 +1,6 @@
#!/bin/bash #!/bin/bash
echo "Создание скриптов из шаблонов с параметрами и сохранение их в каталогах проектов." echo "Создание скриптов из шаблонов с параметрами и сохранение их в каталогах проектов."
export remote="git.org.ru" && source info_param.sh export domain="git.org.ru" && source info_param.sh
export basedir="$PWD" # текущая папка export basedir="$PWD" # текущая папка
# обновление списка исключений # обновление списка исключений
function update_gitignore { function update_gitignore {
@ -43,7 +43,7 @@ function compose {
fi fi
wiki="" # оглавление по страницам вёб-сайта wiki="" # оглавление по страницам вёб-сайта
if [ -f "$dir/WIKI.md" ]; then if [ -f "$dir/WIKI.md" ]; then
if [ "$remote" == "hub.mos.ru" ]; then if [ "$domain" == "hub.mos.ru" ]; then
wiki="$(uni2ascii -aU -qpsn "$dir/WIKI.md")" wiki="$(uni2ascii -aU -qpsn "$dir/WIKI.md")"
else else
wiki="$(basenc "$dir/WIKI.md" --base64 -w0)" wiki="$(basenc "$dir/WIKI.md" --base64 -w0)"
@ -52,13 +52,13 @@ function compose {
# скрипт для создания удалённого репозитория # скрипт для создания удалённого репозитория
{ {
echo "#!/bin/bash" echo "#!/bin/bash"
echo "remote=\"$remote\"" echo "domain=\"$domain\""
echo "owner=\"$owner\"" echo "owner=\"$owner\""
echo "user=\"golovin\"" echo "user=\"golovin\""
echo "repo=\"$repo\"" echo "repo=\"$repo\""
echo "description=\"$description\"" echo "description=\"$description\""
echo "wiki=\"$wiki\"" echo "wiki=\"$wiki\""
if [ "$remote" == "hub.mos.ru" ]; then if [ "$domain" == "hub.mos.ru" ]; then
echo "token=\"$(cat "$basedir/.token_gitlab")\"" echo "token=\"$(cat "$basedir/.token_gitlab")\""
cat "$basedir/repo_gitlab.tmpl.sh" cat "$basedir/repo_gitlab.tmpl.sh"
else else
@ -69,7 +69,7 @@ function compose {
# скрипт для создания локального репозитория # скрипт для создания локального репозитория
{ {
echo "#!/bin/bash" echo "#!/bin/bash"
echo "remote=\"$remote\"" echo "domain=\"$domain\""
echo "owner=\"$owner\"" echo "owner=\"$owner\""
echo "repo=\"$repo\"" echo "repo=\"$repo\""
echo "dir=\"$dir\"" echo "dir=\"$dir\""

View file

@ -1,4 +1,4 @@
if [ -z "$remote" ] || [ -z "$token" ] || [ -z "$owner" ] || [ -z "$repo" ] || [ -z "$description" ] || [ -z "$user" ]; then if [ -z "$domain" ] || [ -z "$token" ] || [ -z "$owner" ] || [ -z "$repo" ] || [ -z "$description" ] || [ -z "$user" ]; then
echo "Не указаны обязательные параметры." && exit 1 echo "Не указаны обязательные параметры." && exit 1
fi fi
if [ -z "$1" ]; then if [ -z "$1" ]; then
@ -8,7 +8,7 @@ seconds=5
time_ms="$(date '+%s%3N')" time_ms="$(date '+%s%3N')"
if [ -z "$1" ] || [ "$1" == "delete" ]; then if [ -z "$1" ] || [ "$1" == "delete" ]; then
echo "Удаление старого репозитория." echo "Удаление старого репозитория."
curl -X DELETE "https://$remote/api/v1/repos/$owner/$repo" \ curl -X DELETE "https://$domain/api/v1/repos/$owner/$repo" \
-H "Authorization: token $token" \ -H "Authorization: token $token" \
-H "Accept: application/json" -i -H "Accept: application/json" -i
echo "Ожидание $seconds с." echo "Ожидание $seconds с."
@ -16,7 +16,7 @@ if [ -z "$1" ] || [ "$1" == "delete" ]; then
fi fi
if [ -z "$1" ] || [ "$1" == "create" ]; then if [ -z "$1" ] || [ "$1" == "create" ]; then
echo "Создание нового репозитория пользователя." echo "Создание нового репозитория пользователя."
curl -X POST "https://$remote/api/v1/user/repos" \ curl -X POST "https://$domain/api/v1/user/repos" \
-H "Authorization: token $token" \ -H "Authorization: token $token" \
-H "Accept: application/json" \ -H "Accept: application/json" \
-H "Content-Type: application/json" -d "{ \"name\": \"$repo\", \"description\": \"$description\" }" -i -H "Content-Type: application/json" -d "{ \"name\": \"$repo\", \"description\": \"$description\" }" -i
@ -24,7 +24,7 @@ if [ -z "$1" ] || [ "$1" == "create" ]; then
sleep "$seconds" sleep "$seconds"
if [ "$user" != "$owner" ]; then if [ "$user" != "$owner" ]; then
echo "Перемещение репозитория в группу." echo "Перемещение репозитория в группу."
curl -X POST "https://$remote/api/v1/repos/$user/$repo/transfer" \ curl -X POST "https://$domain/api/v1/repos/$user/$repo/transfer" \
-H "Authorization: token $token" \ -H "Authorization: token $token" \
-H "Accept: application/json" \ -H "Accept: application/json" \
-H "Content-Type: application/json" -d "{ \"new_owner\": \"$owner\" }" -i -H "Content-Type: application/json" -d "{ \"new_owner\": \"$owner\" }" -i
@ -35,7 +35,7 @@ fi
if [ -z "$1" ] || [ "$1" == "options" ]; then if [ -z "$1" ] || [ "$1" == "options" ]; then
if [ "$wiki" ]; then if [ "$wiki" ]; then
echo "Добавление страницы wiki в репозиторий." echo "Добавление страницы wiki в репозиторий."
curl -X POST "https://$remote/api/v1/repos/$owner/$repo/wiki/new" \ curl -X POST "https://$domain/api/v1/repos/$owner/$repo/wiki/new" \
-H "Authorization: token $token" \ -H "Authorization: token $token" \
-H "Accept: application/json" \ -H "Accept: application/json" \
-H "Content-Type: application/json" -d "{ \"content_base64\": \"$wiki\", \"title\": \"Home\" }" -i -H "Content-Type: application/json" -d "{ \"content_base64\": \"$wiki\", \"title\": \"Home\" }" -i
@ -44,7 +44,7 @@ if [ -z "$1" ] || [ "$1" == "options" ]; then
has_wiki=false has_wiki=false
fi fi
echo "Изменение свойств репозитория / отключение ненужного." echo "Изменение свойств репозитория / отключение ненужного."
curl -X PATCH "https://$remote/api/v1/repos/$owner/$repo" \ curl -X PATCH "https://$domain/api/v1/repos/$owner/$repo" \
-H "Authorization: token $token" \ -H "Authorization: token $token" \
-H "Accept: application/json" \ -H "Accept: application/json" \
-H "Content-Type: application/json" -d "{ -H "Content-Type: application/json" -d "{
@ -61,7 +61,7 @@ if [ -z "$1" ] || [ "$1" == "options" ]; then
picture="website" picture="website"
fi fi
avatar=$(basenc "../pomodoro/pictures/$picture.jpg" --base64 -w0) avatar=$(basenc "../pomodoro/pictures/$picture.jpg" --base64 -w0)
curl -X POST "https://$remote/api/v1/repos/$owner/$repo/avatar" \ curl -X POST "https://$domain/api/v1/repos/$owner/$repo/avatar" \
-H "Authorization: token $token" \ -H "Authorization: token $token" \
-H "Accept: application/json" \ -H "Accept: application/json" \
-H "Content-Type: application/json" -d "{ \"image\": \"$avatar\" }" -i -H "Content-Type: application/json" -d "{ \"image\": \"$avatar\" }" -i

View file

@ -1,4 +1,4 @@
if [ -z "$remote" ] || [ -z "$token" ] || [ -z "$owner" ] || [ -z "$repo" ] || [ -z "$description" ] || [ -z "$user" ]; then if [ -z "$domain" ] || [ -z "$token" ] || [ -z "$owner" ] || [ -z "$repo" ] || [ -z "$description" ] || [ -z "$user" ]; then
echo "Не указаны обязательные параметры." && exit 1 echo "Не указаны обязательные параметры." && exit 1
fi fi
if [ -z "$1" ]; then if [ -z "$1" ]; then
@ -8,7 +8,7 @@ seconds=5
time_ms="$(date '+%s%3N')" time_ms="$(date '+%s%3N')"
if [ -z "$1" ] || [ "$1" == "delete" ]; then if [ -z "$1" ] || [ "$1" == "delete" ]; then
echo "Удаление старого репозитория." echo "Удаление старого репозитория."
curl -i -X DELETE "https://$remote/api/v4/projects/$owner%2F$repo" \ curl -i -X DELETE "https://$domain/api/v4/projects/$owner%2F$repo" \
-H "PRIVATE-TOKEN: $token" \ -H "PRIVATE-TOKEN: $token" \
-H "Content-Type: application/json" -d "{\"permanently_remove\": \"true\", \"full_path\": \"$owner/$repo\"}" -H "Content-Type: application/json" -d "{\"permanently_remove\": \"true\", \"full_path\": \"$owner/$repo\"}"
echo echo
@ -17,7 +17,7 @@ if [ -z "$1" ] || [ "$1" == "delete" ]; then
fi fi
if [ -z "$1" ] || [ "$1" == "create" ]; then if [ -z "$1" ] || [ "$1" == "create" ]; then
echo "Создание нового репозитория пользователя." echo "Создание нового репозитория пользователя."
curl -i -X POST "https://$remote/api/v4/projects" \ curl -i -X POST "https://$domain/api/v4/projects" \
-H "PRIVATE-TOKEN: $token" \ -H "PRIVATE-TOKEN: $token" \
-H "Content-Type: application/json" -d "{\"name\": \"$repo\", \"description\": \"$description\"}" -H "Content-Type: application/json" -d "{\"name\": \"$repo\", \"description\": \"$description\"}"
echo echo
@ -25,7 +25,7 @@ if [ -z "$1" ] || [ "$1" == "create" ]; then
sleep "$seconds" sleep "$seconds"
if [ "$user" != "$owner" ]; then if [ "$user" != "$owner" ]; then
echo "Перемещение репозитория в группу." echo "Перемещение репозитория в группу."
curl -i -X PUT "https://$remote/api/v4/projects/$user%2F$repo/transfer?namespace=$owner" \ curl -i -X PUT "https://$domain/api/v4/projects/$user%2F$repo/transfer?namespace=$owner" \
-H "PRIVATE-TOKEN: $token" -H "PRIVATE-TOKEN: $token"
echo echo
echo "Ожидание $seconds с." echo "Ожидание $seconds с."
@ -35,7 +35,7 @@ fi
if [ -z "$1" ] || [ "$1" == "options" ]; then if [ -z "$1" ] || [ "$1" == "options" ]; then
if [ "$wiki" ]; then if [ "$wiki" ]; then
echo "Добавление страницы wiki в репозиторий." echo "Добавление страницы wiki в репозиторий."
curl -i -X POST "https://$remote/api/v4/projects/$owner%2F$repo/wikis" \ curl -i -X POST "https://$domain/api/v4/projects/$owner%2F$repo/wikis" \
-H "PRIVATE-TOKEN: $token" \ -H "PRIVATE-TOKEN: $token" \
-H "Content-Type: application/json" -d "{\"content\": \"$wiki\", \"title\": \"Home\"}" -H "Content-Type: application/json" -d "{\"content\": \"$wiki\", \"title\": \"Home\"}"
echo echo
@ -44,7 +44,7 @@ if [ -z "$1" ] || [ "$1" == "options" ]; then
has_wiki="disabled" has_wiki="disabled"
fi fi
echo "Изменение свойств репозитория / отключение ненужного." echo "Изменение свойств репозитория / отключение ненужного."
curl -i -X PUT "https://$remote/api/v4/projects/$owner%2F$repo" \ curl -i -X PUT "https://$domain/api/v4/projects/$owner%2F$repo" \
-H "PRIVATE-TOKEN: $token" \ -H "PRIVATE-TOKEN: $token" \
-H "Content-Type: application/json" -d "{ -H "Content-Type: application/json" -d "{
\"emails_disabled\": \"true\", \"emails_disabled\": \"true\",
@ -87,7 +87,7 @@ if [ -z "$1" ] || [ "$1" == "options" ]; then
if [ "$user" != "$owner" ]; then if [ "$user" != "$owner" ]; then
picture="website" picture="website"
fi fi
curl -i -X PUT "https://$remote/api/v4/projects/$owner%2F$repo" \ curl -i -X PUT "https://$domain/api/v4/projects/$owner%2F$repo" \
-H "PRIVATE-TOKEN: $token" \ -H "PRIVATE-TOKEN: $token" \
-F "avatar=@../pomodoro/pictures/$picture.jpg" -F "avatar=@../pomodoro/pictures/$picture.jpg"
echo echo

View file

@ -1,4 +1,4 @@
if [ -z "$remote" ] || [ -z "$owner" ] || [ -z "$repo" ] || [ -z "$dir" ]; then if [ -z "$domain" ] || [ -z "$owner" ] || [ -z "$repo" ] || [ -z "$dir" ]; then
echo "Не указаны обязательные параметры." && exit 1 echo "Не указаны обязательные параметры." && exit 1
fi fi
echo "Создание локального репозитория, подключение к удалённому и передача данных." echo "Создание локального репозитория, подключение к удалённому и передача данных."
@ -6,12 +6,12 @@ seconds=3
time_ms="$(date '+%s%3N')" time_ms="$(date '+%s%3N')"
rm -rf .git rm -rf .git
git init -b master git init -b master
git remote add "$remote" "git@$remote:$owner/$repo.git" git remote add "$domain" "git@$domain:$owner/$repo.git"
git add .git* git add .git*
git commit -m "Инициализация / $dir" git commit -m "Инициализация / $dir"
if [ "$remote" == "hub.mos.ru" ]; then if [ "$domain" == "hub.mos.ru" ]; then
echo "Второй пуш, потому что лингвист с первого раза не срабатывает." echo "Второй пуш, потому что лингвист с первого раза не срабатывает."
git push -u "$remote" master git push -u "$domain" master
echo "Ожидание $seconds с." echo "Ожидание $seconds с."
sleep $seconds sleep $seconds
fi fi
@ -46,5 +46,5 @@ find . -type f -not -path "*/.*" -not -path "./_site*" | LC_COLLATE=C sort -r |
git add "$file" git add "$file"
git commit -m "${file#*/}" git commit -m "${file#*/}"
done done
git push -u "$remote" master git push -u "$domain" master
echo "Общее время выполнения: $(("$(date '+%s%3N')" - "$time_ms")) мс." echo "Общее время выполнения: $(("$(date '+%s%3N')" - "$time_ms")) мс."