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

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

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

Оффлайн Poisk

  • Новичок
  • *
  • Сообщений: 19
  • Репутация: +1/-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

  • Активный участник
  • Ветеран
  • ****
  • Сообщений: 5695
  • Репутация: +146/-0
  • Старый чайник
ничего кроме одного способа не нашёл.
Здесь описано три, но работает только wc.
Огласите весь скрипт пожалуйста.
Моноблок Lenovo IdeaCentre c200
Netbook Acer 722 c6ckk (AMD C-50 Ontario, Radeon HD 6250)
Nettop Asus Eee Box PC B202 (atom N270, intel GMA 950)

Оффлайн Poisk

  • Новичок
  • *
  • Сообщений: 19
  • Репутация: +1/-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

  • Новичок
  • *
  • Сообщений: 19
  • Репутация: +1/-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

  • Новичок
  • *
  • Сообщений: 19
  • Репутация: +1/-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

  • Новичок
  • *
  • Сообщений: 19
  • Репутация: +1/-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

  • Новичок
  • *
  • Сообщений: 19
  • Репутация: +1/-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

  • Активный участник
  • Ветеран
  • ****
  • Сообщений: 5206
  • Репутация: +109/-0
    • RoDoN
Вместо 5 серий можно было прикрепить файл во вложении в одном сообщении и не мучить ни себя, ни читателей кода

Acer Aspire One AO751h (Atom Z520, Intel GMA500)
Acer Extensa 5620Z (T7500, Intel 965GM)
PuppyRus-JWM-13.12, PRA, Upup Precise, Tahr Puppy, Runtu 14.04 XFCE.

Оффлайн Poisk

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

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

Оффлайн DdShurick

  • Активный участник
  • Ветеран
  • ****
  • Сообщений: 5695
  • Репутация: +146/-0
  • Старый чайник
А у Вас есть интерес в использовании?
За долгие годы такой необходимости не возникало, но задача интересная. Вы хотите сделать аналог cp -a с укорочением длинных имён на лету? Я правильно вас понял?
Моноблок Lenovo IdeaCentre c200
Netbook Acer 722 c6ckk (AMD C-50 Ontario, Radeon HD 6250)
Nettop Asus Eee Box PC B202 (atom N270, intel GMA 950)

Оффлайн Poisk

  • Новичок
  • *
  • Сообщений: 19
  • Репутация: +1/-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

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

Оффлайн DdShurick

  • Активный участник
  • Ветеран
  • ****
  • Сообщений: 5695
  • Репутация: +146/-0
  • Старый чайник
И если Вам доводилось, то как в Си преобразовывали строку char в int?
Использовал в декодере sms sscanf.sscanf(str,"%x", &c);
putwchar(c);
Моноблок Lenovo IdeaCentre c200
Netbook Acer 722 c6ckk (AMD C-50 Ontario, Radeon HD 6250)
Nettop Asus Eee Box PC B202 (atom N270, intel GMA 950)