Сайт | Скачать | Видео | Wiki

Автор Тема: Как подсчитать количество байт занимаемое строкой ?  (Прочитано 4734 раз)

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

Оффлайн Poisk

  • Пользователь
  • **
  • Сообщений: 45
  • Репутация: +2/-0
  • Автор темы
Помогите если знаете, как подсчитать количество байт занимаемое строкой.

Пытался найти ответ но ничего кроме одного способа не нашёл.
Вот простой код считает байты занимаемые строкой "DDЮЮ", но..

Код
a=`echo "DDЮЮ" | wc -c` 
echo "$a"
вывод: 7

в скрипте который я пишу эта строка в цикле идёт. И насколько я понял эта строка сильно тормозит.

ПС. Скрипт должен автоматически на лету переименовывать файлы с длинными именами и связанные с ними каталоги "*_files" для переноса их с системы NTFS на ext2, ext3, ext4. Может я напрасно трачу время и эта проблема уже решена? Для тех кто не в курсе, если ваши html-файлы и любые другие, имели длинные имена и хранились на NTFS разделе, то в PyppyRus вы не сможете перенести их на типичный для Linux раздел ext2/3/4. Потому что количество байт требуемое для символов русской кодировки больше чем количество самих символов, что иногда превысит ограничение ext2/3/4 в 255 байт для имён файлов и каталогов.
« Последнее редактирование: 02 Апрель 2018, 13:24:00 от Poisk »

Оффлайн DdShurick

  • Это Риччи
  • Активный участник
  • Ветеран
  • ****
  • Сообщений: 8635
  • Репутация: +187/-2
  • Старый чайник
ничего кроме одного способа не нашёл.
Здесь описано три, но работает только wc.
Огласите весь скрипт пожалуйста.
Моноблок Lenovo IdeaCentre c200 (Intel Atom D525, Intel GMA 3150, 2 Gb RAM) Richy64
Nettop Acer Aspire Revo R3610 (Atom N330, nVidia GeForce 9400, 3 Gb RAM) Richy64

Оффлайн Poisk

  • Пользователь
  • **
  • Сообщений: 45
  • Репутация: +2/-0
  • Автор темы
Здесь описано три, но работает только wc.
Огласите весь скрипт пожалуйста.

Рассмеялся когда прошёл по Вашей ссылке. :D
Не только потому, что я от туда взял метод, но и потому, что там указано, что
с кириллицей данный метод не работает (Это если задача считать символы). Но для нашей цели выходит только этот метод и работает с кириллицей. Для кого то это мусор ???, а для нас единственный, и как выяснилось, не предназначавшийся для кириллицы инструмент :laugh:.

Про код. Хотел выложить по завершении.
Смущали несколько моментов.
- Я не придерживаюсь BASH-стиля.
- В коде присутствует тупиковая ветвь алгоритма, ещё не убрал. С программированием на BASH знаком 4-е дня, точнее суток :)(нужен зевающий смайлик). Не стал отлавливать почему код на выходе выдавал имена длинной 251..253 байта, хотя ожидалось 253..255. И переделал алгоритм на более "прямой","грубый", как мне казалось, и получил максимально возможный результат 254..255 байт.
- Хотел доделать "макро-управление" - чтобы было достаточно указать каталог источника и приёмника, а подкаталоги с заданным уровнем вложений и остальное делал бы код. А ещё лучше с GUI, но с ним пока ни минуты не знаком.

Комментарии старался написать сразу внятно, предполагая, что может кому пригодится.

Код
 #!/bin/bash
# ВНИМАНИЕ! код в разработке. генерирует не нужные для комфорта в жизни,
# всякие текстовые файлы и содержит балласт. Автор ещё не успел освоить системные
# темп-файлы и т.п "высокие" технологии BASH-е кодинга.
# Но советы, как сделать лучше - приветствуются.

IFS_B=$IFS # эти строки появились при поиске ошибки. Они не нужны.
IFS=$'\n'


    # 2 ---------------------------------------------------------   
# 2 находим файл с не допустимо длинным именем
# имена всех файлов найденных в каталоге сохраняем в разных вариантах в базах

echo "----- Начало всего ----"

set_size=$1         # требуемая, новая длина имени файла
post_size=$2 # коли-во символов в окончании имени остающихся на своих местах
if [[ $1 = '' ]]
then   set_size=255
post_size=12
fi
# set_size=255
# post_size=12



mas_b=''                 # Массив базовых имён
mas_e=''                 # Массив расширений имён
mas_k=''                 # Массив имён без расширений
mas_s=''                 # Массив размеров имён
mas_old_new_file=''  # Массив старых и новых имен файлов
mas_old_new_dir=''   # Массив старых и новых имён директорий

post_name='' # временная переменная для размещения сохраняемых окончаний имён
if [[ $3 = '' ]]
then
post_post_dir="_files" # пост-пост-фикс для директорий HTML
fi

pos_post=0 # Позиция окончания имени файла. вычисляется автоматически.
ext_post=''         # временная для расширений
ext_bait=0          # временная для кол-ва байт для расширения
right_bait=0        # временная переменная для точного подсчёта смещения от правого края имени
razdel='~-~'          # символ(ы) разделитель между первой частью и окончанием имени

# продолжение следует...
А у Вас есть интерес в использовании?
« Последнее редактирование: 02 Апрель 2018, 23:36:49 от Poisk »

Оффлайн Poisk

  • Пользователь
  • **
  • Сообщений: 45
  • Репутация: +2/-0
  • Автор темы
Мне "везёт" на разного рода ограничения :D. Широту мысли (по Вашей просьбе. Т.е снимаю ответственность с себя) будем проталкивать через объективную реальность размером в 5000 знаков :laugh: По ходу придётся писать код не только рубящий имена файлов до 255 байт, но и собственные публикации тут до 5000 зн :laugh:
продолжение кода:
Код
razdel_bait=0       # размер в байтах разделителя(ей)
flag_fd='' # флаг для переименования только файла либо ещё и
                    # связанного с ним каталога. Два значения: file_only file_dir
count_file=0        # подсчёт файлов готовых к переименованию
count_dir=0         # подсчёт каталогов готовых к переименованию

fun_del () {
if [  -f "$" ]       # Проверка существования каталога
then
rm ./filename_zale1.txt                  # база размеров имён файлов
fi
if [  -f "$" ]       # Проверка существования каталога
then
rm ./filename-ext.txt                    # база расширений файлов
fi
if [  -f "$" ]       # Проверка существования каталога
then
rm ./filename_mas_k.txt                  # база имён без расширений
fi
if [  -f "$" ]       # Проверка существования каталога
then
rm ./filename-base.txt                  # база базовых имён файлов
fi
if [  -f "$" ]       # Проверка существования каталога
then
rm ./filename-full.txt                   # база полных имён файлов
fi
if [  -f "$" ]       # Проверка существования каталога
then
rm ./filename-tmp.tmp                    # временный файл
fi
}

fun_del
if [  -f "$" ]       # Проверка существования каталога
then
echo -n '' > mas_old_new_file.txt
fi
if [  -f "$" ]       # Проверка существования каталога
then
echo -n '' > mas_old_new_dir.txt #  СОЗДАЁМ БАЗУ РАЗМЕРОВ ИМЁН ФАЙЛОВ
fi
if [  -f "$" ]       # Проверка существования каталога
then
echo -n '' > mas_norm_file_dir.txt            # Список измений
fi




#rm ./mas_old_new_file.txt                # база изменений имён файлов
#rm ./mas_old_new_dir.txt                 # база изменений имён каталогов
#rm ./mas_norm_file_dir.txt               # база не требующих изменений всех имён
                           

#echo -n "" > filename_mas_k.txt
#echo -n '' > filename_zale1.txt #  СОЗДАЁМ БАЗУ РАЗМЕРОВ ИМЁН ФАЙЛОВ
#echo -n '' > filename_before_after.txt            # Список измений

#echo -n "" > filename_mas_k.txt
#echo -n '' > filename_zale1.txt #  СОЗДАЁМ БАЗУ РАЗМЕРОВ ИМЁН ФАЙЛОВ
#echo -n '' > filename_before_after.txt            # Список измений


find $PWD -maxdepth 1 -type f > filename-full.txt  # ПОЛНОЕ ИМЯ составляем без включения подкаталогов
#echo -n '' > filename-base.txt  # база: БАЗОВОЕ ИМЯ

i1=0
while read LINE_full              # извлечение из полного пути базового имени и расширения
 do   #echo "$LINE_full" | cut -f1 -d":" >> filename-tmp.tmp

mas_b[i1]=`basename "$LINE_full"`                    # БАЗОВОЕ ИМЯ заносим в массив
      #filename=$(basename "$f")
  #extension=${filename##*.}
   
    echo  `basename "$LINE_full"` >> filename-base.txt ; # БАЗОВОЕ ИМЯ заносим в файл
# echo mas_b_[$i1]= "${mas_b[$i1]}"

    filename1=${LINE_full%.*}     # Получаем имя файла без расширения и если файл без расширения, то тут создаётся ошибка с расширением которую исправляем далее

    #mas_k[i1]=`basename "${filename1%.????}"`         # Имя файла без расширения заносим в массив
  mas_k[i1]=`basename $filename1`         # Имя файла без расширения заносим в массив

    extension=${LINE_full##*.}    # Получаем расширение файла
    echo "${mas_k[$i1]}" >> filename_mas_k.txt
#    echo "mas_k[$i1]-------------${mas_k[$i1]}" 

Оффлайн Poisk

  • Пользователь
  • **
  • Сообщений: 45
  • Репутация: +2/-0
  • Автор темы
Santa Bahrbara № 3
Код
    # компенсатор ошибки в случае если имя файла без точки
     # =============== вставка начало =========================================
    if [[ "$filename1" = "$extension" ]] #сравнение строк, внимание на пробелы и скобки
        then  extension=''
        else  extension=".$extension"
    fi #конец сравнения ---- ошибка с пустым расширением исправлена
    echo "$extension" >> filename-ext.txt
    mas_e[i1]=$extension          # Заносим в базу расширение
   
   echo ${mas_b[$i1]} | wc -c >> filename_zale1.txt
   trr=$(echo ${mas_b[$i1]} | wc -c)
#   echo "{#mas_b[$i1]} ${#mas_b[$i1]} ============================================"
   while read tt
   do mas_s[$i1]=$tt   
   done < ./filename_zale1.txt
   
#    echo "mas_s_[$i1]=  ${mas_s[$i1]}"
    # --- оценка превышения порога на этапе подсчёта длины имени файла
    #if [[ "${mas_s[$i1]}" -ge $set_size ]] #сравнение чисел
        #then    echo "$mas_s[$i1] - превышение лимита: $set_size"
        #else    echo "else  $mas_s[$i1] - лимит не превышен: $set_size +++++++++++++++++"
    #fi #конец сравнения
   
     # =============== вставка конец =========================================

let "i1= i1 + 1"
done   <  ./filename-full.txt        # END  поиск подходящей длины имени файла
# ========================== СБОР ИНФОРМАЦИИ ЗАВЕРШЁН =========================
# ========================== СБОР ИНФОРМАЦИИ ЗАВЕРШЁН =========================

# TEST
echo
echo "---------------- Тест --------------------------"

razmer1=${#mas_b[*]}
#echo "razmer1 = $razmer1"
#echo " ------     Базовые имена каталога:"
#for (( i=0; i<razmer1; i++ ))
    #do                             echo "$i. ${mas_b[$i]}"
    #done

razmer2=${#mas_e[*]}
#echo; echo  "razmer2 = $razmer2" ; echo " ------     расширения:"
#for (( i=0; i<razmer2; i++ ))
    #do                             echo "$i. ${mas_e[$i]}"
    #done 
   
echo   
razmer3=${#mas_s[*]}
#echo "razmer3 = $razmer3" ;         echo " ------     длины имён:"
#for (( i=0; i<razmer3; i++ ))
    #do                              echo "$i. ${mas_s[$i]}"
    #done   
     
if [[ $razmer1 -eq $razmer2 || $razmer2 -eq $razmer3 ]]  #
    then                            echo " ---   Тест пройден успешно !"
        echo "кол-во элементов в базах сходится."
    else           echo " ---   ТЕСТ НЕ ПРОЙДЁН! Не сходятся количества объектов !"
fi
  echo "---------------- Тест завершён -----------------" ; echo
# -------------------------- TEST END


# -------------------------- ФУНКЦИИ ------------------------------------------
# --- Функция проверки подходящей длины
 
razmer1=${#mas_b[*]}
#echo "razmer1 = $razmer1";           echo " ------     Базовые имена каталога:"
#for (( i=0; i<razmer1; i++ ))
    #do                               echo "$i. ${mas_b[$i]}"
    #done
#echo 

#  End - Функция проверки подходящей длины - End
# -------------------------- КОНЕЦ ФУНКЦИЙ

# -----------------------------------------------------------------------------
# -------------------------- ПЕРЕИМЕНОВАНИЯ -----------------------------------

iter_1=${#mas_b[*]}     # кол-во перебираемых имён
echo;               echo " --- оценка превышения порога размеров именён файлов"

for (( i=0; i<iter_1; i++ )) # ПЕРЕБИРАЕМ ПО КОЛ-ВУ БАЗОВЫХ ИМЕН
 do

                     # --- оценка превышения порога размера имени файла
z1=${mas_s[$i]}
if [[ $z1 -ge $set_size ]] # если длина имени больше требуемого то...
then

#echo " >>- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
#echo "проверка существования каталога с постфиксом из переменой post_post_dir: $post_post_dir"
    #echo "${mas_s[$i]} байт занимает это длинное имя:"
#echo "${mas_b[$i]}"
# проверка существования каталога с постфиксом из переменой: post_post_dir
name_dir="${mas_k[$i]}$post_post_dir"
#echo "name_dir: $name_dir"
if [ ! -d "$name_dir" ]       # Проверка существования каталога связанного с файлом.

Оффлайн Poisk

  • Пользователь
  • **
  • Сообщений: 45
  • Репутация: +2/-0
  • Автор темы
Santa Bahrbara № 4

Код
           then
               flag_fd[i]="file_only" # флаг для переименования без каталога 
               #echo "flag_fd= ${flag_fd[$i]}"
               #echo;echo "Каталог связанный с файлом не найден.~~~~~~~~~~~~~~~~~~~~~~~~~~~";echo;echo
               #exit $E_NOFILE
           else
               flag_fd[i]="file_dir" # флаг для переименования и каталога 
               #echo "flag_fd[$i]= ${flag_fd[$i]}"
               #echo  "найден связанный с файлом каталог:"; echo "\"$name_dir\"";echo;echo
               echo "$name_dir" >> mas_old_new_dir.txt # сохраняем старое имя каталога
               
                    #flag_fd[i]="file_only" # флаг для переименования только файла либо ещё и
                    ## связанного с ним каталога. Два значения: file_only file_dir
       flag_fd[i]="file_dir" # флаг для переименования и каталога       
               
               if [[ ${#post_post_dir} -gt ${#mas_e[$i]}  ]]   # что длиннее то и примем за смещающую поправку right_bait от правого края имени
                   then # если постфикс каталога длиннее имени расширения
                       echo " ===>>  постфикс каталога длиннее имени расширения ==="
                        echo "$post_post_dir = ${#post_post_dir} "
                        echo ".${mas_e[$i]} = ${#mas_e[$i]}" 
                        echo " ===  постфикс каталога длиннее имени расширения <<==="
                       right_bait=${#post_post_dir}  # отступ справа при проверке вместимости в требуемое кол-во байт
               
                       right_bait=$(echo $post_post_dir | wc -c)
                       echo "right_bait= $right_bait"                                   
                   else # если постфикс каталога не длиннее имени расширения
                       echo " ===>>  постфикс имени расширения длиннее каталога ==="
                       echo ".${mas_e[$i]} = ${#mas_e[$i]}" 
                       echo; echo "$post_post_dir = ${#post_post_dir} "
                       echo " ===  постфикс имени расширения длиннее каталога <<==="
                       ext_post=${mas_e[$i]} #для измерения байт выделенных расширению

                       right_bait=$(echo $ext_post | wc -c)
                       
                       echo "right_bait= $right_bait"
               fi   
               
           #exit $E_NOFILE           
        fi

echo "проверка существования каталога с постфиксом из переменой post_post_dir"
echo " - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - <<"

echo -n '' > filename-tmp.tmp
dlin1=`echo ${mas_k[$i]} | awk '{print length}'`
tz3=`expr $dlin1 - $post_size`
echo "tz3= $tz3"
echo "mas_s[$i]= ${mas_s[$i]}"
post_name="${mas_k[$i] : $tz3 : $post_size}" #012e
echo "mas_k[$i] = ${mas_k[$i]}"
post_bait=$(echo $post_name | wc -c)
razdel_bait=$(echo $razdel | wc -c)   
echo "post_bait = $post_bait +++++++++++==========++++++++++++"
echo "post_name = $post_name"

for (( j=$z1; j > 20; j-- ))    # найти приемлемую длину имени файла
do

              tz4=0 # оценочная длина имени каталога
              tz5=0 # оценочная длина имени файла
                    # сборка имени каталога если
                   
                   
                   if [[ "${flag_fd[$i]}" = "file_dir" ]]
                       then
                            mas_new_dir[i]="${mas_k[$i]:0:$j}$razdel$post_name$post_post_dir"
                            tz4=$(echo ${mas_new_dir[$i]} | wc -c) 
                   fi
                   
                   #  сборка имени файла
                   mas_new_file[i]="${mas_k[$i]:0:$j}$razdel$post_name${mas_e[$i]}" #
                   tz5=$(echo ${mas_new_file[$i]} | wc -c) 

Оффлайн Poisk

  • Пользователь
  • **
  • Сообщений: 45
  • Репутация: +2/-0
  • Автор темы
Заключительная 5-я серия. Уффф уж эти "Прокрустовы ложа" и копи-пастээээ... А ведь есть ещё и профессия такая в Интернете, статьи пере-"компилировать" , я им сочувствую.
Код
                   if [[ $tz4 -le $set_size && $tz5 -le $set_size ]] 
                      then echo " >>>>>  >  >  >  >  >  >  >  >  >  >  >  >  > "; echo
                           echo "файл mas_new_file[$i]:"
                           echo "${mas_new_file[$i]}"
                           tz5=$(echo ${mas_new_file[$i]} | wc -c) 
                           echo "занимает в памяти: $tz5  байт"
                           echo 

                           echo "КАТАЛОГ связаный с файлом mas_new_dir[$i]:"
                           echo "${mas_new_dir[$i]}"
                           tz4=$(echo ${mas_new_dir[$i]} | wc -c) 
                           echo "занимает в памяти: $tz4  байт"
                           echo " <  <  <  <  <  <  <  <  <  <  <  <  <  <<<<< "
                           let "count_file= $count_file + 1"
                           if [[ "${flag_fd[$i]}" = "file_dir" ]]
                                then let "count_dir= $count_dir + 1"
                               
                                echo  "${mas_new_dir[$i]}" >> mas_old_new_dir.txt 
                           fi 
                           echo   "${mas_b[$i]}"     >> mas_old_new_file.txt   
                           echo   "${mas_new_file[$i]}" >> mas_old_new_file.txt
                           
                           
                      break
                   fi   
done
else # ветка имён не превышающих критическую длину

echo   "${mas_b[$i]}"     >> mas_norm_file_dir.txt   


fi #конец сравнения

done #         END  - ПЕРЕБИРАЕМ ПО КОЛ-ВУ БАЗОВЫХ ИМЕН -  END

#fun_del
 echo
 echo "   файлов с длинными именами готовых к переименованию: $count_file"
 echo "каталогов с длинными именами готовых к переименованию: $count_dir"
 echo
 echo "= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = "
 echo "= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = "
 IFS=$IFS_B

exit 0 #Выход с кодом 0 (удачное завершение работы скрипта)

Оффлайн RoDoN

  • Активный участник
  • Ветеран
  • ****
  • Сообщений: 6282
  • Репутация: +141/-0
Вместо 5 серий можно было прикрепить файл во вложении в одном сообщении и не мучить ни себя, ни читателей кода
Lenovo G500 (i3-3110M, 8 Гб, Intel + Radeon HD 8570)
PRA 16.12 JWM, Runtu 22.04 x64 XFCE

Оффлайн Poisk

  • Пользователь
  • **
  • Сообщений: 45
  • Репутация: +2/-0
  • Автор темы
...и не мучить...
Посыпаю голову пеплом :angel:. Хотя мои планы относительно момента публикации кода были нарушены, пришлось посуетиться, подредактировать. Собственно о 5000 знаков узнал только из попытки опубликовать, когда уже напечатал Вам весёлое послание. Чё же, зря трудился? - подумал. Так что селя ви. 
А у Вас есть интерес в использовании?

Вот код:
« Последнее редактирование: 03 Апрель 2018, 03:52:42 от Poisk »

Оффлайн DdShurick

  • Это Риччи
  • Активный участник
  • Ветеран
  • ****
  • Сообщений: 8635
  • Репутация: +187/-2
  • Старый чайник
А у Вас есть интерес в использовании?
За долгие годы такой необходимости не возникало, но задача интересная. Вы хотите сделать аналог cp -a с укорочением длинных имён на лету? Я правильно вас понял?
Моноблок Lenovo IdeaCentre c200 (Intel Atom D525, Intel GMA 3150, 2 Gb RAM) Richy64
Nettop Acer Aspire Revo R3610 (Atom N330, nVidia GeForce 9400, 3 Gb RAM) Richy64

Оффлайн Poisk

  • Пользователь
  • **
  • Сообщений: 45
  • Репутация: +2/-0
  • Автор темы
Вы хотите сделать аналог cp -a с укорочением длинных имён на лету?
При сохранении из браузера на диск интернет-страниц их имена по умолчанию бывают длинные.
И при последующем их переносе на разделы ext2/3/4 система блокирует их копирование.
Скрипт должен принимать путь к каталогу с подкаталогами в которых по темам отсортированы сохранённые страницы на разделе NTFS. И должен принимать целевой каталог на разделе ext2/3/4.
После старта он должен воссоздать дерево, копировать с укорочением длинных имен и с сохранением в отдельный файл всех изменённых имён. Из этого отдельного файла если понадобиться скрипт будет проводить обратную операцию - восстановление длинных имён с копированием на раздел NTFS.

Почти доделал тот участок кода, про который предполагаю что он медленный. Вынес его в отдельную программу на Си. Там работает мгновенно. Но застопорился то ли на передаче числа из BASH в Си, то ли на преобразовании строки char содержащей число в тип int. Т.е если жёстко выставляю  в коде Си требуемое для FS ограничение=255байт , то всё прекрасно работает. Но задумка была настраивать этот параметр. И вот никак не могу это число перегнать вместе с именем файла из BASH в Си и поставить его там в условие. Точнее ставлю, но там по видимому вылазит другое число. Если из консоли передаю параметры в Си то на экран выводит верный результат работы. Из Баша строки - передаю, число - ни как. Подскажите как передать и вернуть обратно строку-текст и строку-число двумя параметрами? И если Вам доводилось, то как в Си преобразовывали строку char в int?
« Последнее редактирование: 04 Апрель 2018, 23:34:12 от Poisk »

Оффлайн sfs

  • Администратор
  • Ветеран
  • *****
  • Сообщений: 33965
  • Репутация: +231/-0
    • PuppyRus-A
При сохранении из браузера на диск интернет-страниц их имена по умолчанию бывают длинные.
Сохраняйте методом печати в pdf

Оффлайн DdShurick

  • Это Риччи
  • Активный участник
  • Ветеран
  • ****
  • Сообщений: 8635
  • Репутация: +187/-2
  • Старый чайник
И если Вам доводилось, то как в Си преобразовывали строку char в int?
Использовал в декодере sms sscanf.
Код
sscanf(str,"%x", &c);
putwchar(c);
Моноблок Lenovo IdeaCentre c200 (Intel Atom D525, Intel GMA 3150, 2 Gb RAM) Richy64
Nettop Acer Aspire Revo R3610 (Atom N330, nVidia GeForce 9400, 3 Gb RAM) Richy64