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

Автор Тема: shell-script. Разрезать каталог на несколько каталогов определённого размера  (Прочитано 3391 раз)

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

Оффлайн Neyel

  • Ветеран
  • *****
  • Сообщений: 1548
  • Репутация: +28/-0
  • Автор темы
Помогите с написанием скрипта. Нужно разрезать каталог на несколько каталогов определённого размера. Вот что я приблизительно накидал:
Код
directory=...; исходная директория
массив_список_файлов=список_файлов(directory)

until(массив_список_файлов пустой)
do
source_directory=... ; директория куда перемещаются файлы
x=0; общий вес перемещённых файлов
for file in массив_список_файлов
do
        if(x+razmer(file)< 4G)
then
sudo mv file source_directory
x=x+razmer(file)
fi
done
массив_список_файлов=список_файлов(directory)
done

Код
...массив_список_файлов=список_файлов(directory)...
- как получить список файлов (какие команды нужны)

Код
...razmer(file)...
- как узнать размер файла?

Код
until(массив_список_файлов пустой)
- как прописать это условие?

Заранее спасибо  :)

Оффлайн sfs

  • Администратор
  • Ветеран
  • *****
  • Сообщений: 33965
  • Репутация: +231/-0
    • PuppyRus-A
как получить список файлов
ls или find
как узнать размер файла?
du
until(массив_список_файлов пустой)
- как прописать это условие?
for

Оффлайн Neyel

  • Ветеран
  • *****
  • Сообщений: 1548
  • Репутация: +28/-0
  • Автор темы
live@pra-roll:~$ du 001-portwine_dep.pfs
196308  001-portwine_dep.pfs


196308  001-portwine_dep.pfs
нужно с помощью grep (или sed) вырезать из этой строки только размер и преобразовать в число - подскажите как это можно сделать

Кажется нашёл как:
Код
x=".."
x=$(du 001-portwine_dep.pfs)
echo $x|sed 's/\([0-9]*\).*/\1/'
Буду думать дальше  :)
« Последнее редактирование: 02 Ноябрь 2018, 17:26:49 от Neyel »

Оффлайн krasnyh

  • Ветеран
  • *****
  • Сообщений: 5319
  • Репутация: +139/-1
- как получить список файлов (какие команды нужны)
Это?
Код
$ sudo pfspkg 001-portwine_dep.pfs
alsa-plugins
aspell
brotli
cabextract
db
enchant
freeglut
gamin
geoclue2
glew
glibc
gnu-netcat
gst-plugins-base-libs
gstreamer
harfbuzz-icu
hspell
hunspell
hyphen
icoutils
iniparser
ldb
lib32-acl
lib32-alsa-lib
lib32-alsa-plugins
lib32-attr
lib32-bzip2
lib32-dbus
lib32-expat
lib32-flac
lib32-fontconfig
lib32-freetype2
lib32-gcc-libs
lib32-gettext
lib32-giflib
lib32-glib2
lib32-glibc
lib32-glu
lib32-gmp
lib32-gnutls
lib32-harfbuzz
lib32-icu
lib32-lcms2
lib32-libasyncns
lib32-libcap
lib32-libdrm
lib32-libelf
lib32-libffi
lib32-libgcrypt
lib32-libglvnd
lib32-libgpg-error
lib32-libgudev
lib32-libice
lib32-libidn
lib32-libjpeg-turbo
lib32-libldap
lib32-libltdl
lib32-libnl
lib32-libogg
lib32-libpcap
lib32-libpciaccess
lib32-libpng
lib32-libpulse
lib32-libsm
lib32-libsndfile
lib32-libtasn1
lib32-libtiff
lib32-libudev0-shim
lib32-libusb
lib32-libvorbis
lib32-libx11
lib32-libxau
lib32-libxcb
lib32-libxcursor
lib32-libxdamage
lib32-libxdmcp
lib32-libxext
lib32-libxfixes
lib32-libxi
lib32-libxml2
lib32-libxrandr
lib32-libxrender
lib32-libxshmfence
lib32-libxss
lib32-libxtst
lib32-libxxf86vm
lib32-llvm-libs
lib32-lm_sensors
lib32-mesa
lib32-mpg123
lib32-ncurses
lib32-nettle
lib32-openssl
lib32-p11-kit
lib32-pcre
lib32-readline
lib32-systemd
lib32-util-linux
lib32-vulkan-icd-loader
lib32-wayland
lib32-xz
lib32-zlib
libedit
libomxil-bellagio
libudev0-shim
libutempter
libvoikko
libwebp
libxaw
libxslt
llvm-libs
mesa
mesa-demos
mpg123
p7zip
perl
perl-encode-locale
perl-file-listing
perl-html-parser
perl-html-tagset
perl-http-cookies
perl-http-daemon
perl-http-date
perl-http-message
perl-http-negotiate
perl-io-html
perl-libwww
perl-lwp-mediatypes
perl-net-http
perl-parse-yapp
perl-try-tiny
perl-uri
perl-www-robotrules
python2-wxpython3
samba
smbclient
tevent
texinfo
vulkan-icd-loader
webkit2gtk
woff2
wxgtk-common
wxgtk2
wxgtk3
xbitmaps
xorg-luit
xorg-xmessage
xterm
zenity

Оффлайн k0l0p0k

  • Ветеран
  • *****
  • Сообщений: 1611
  • Репутация: +27/-1
как узнать размер файла?
помимо du можно использовать
2) stat
3) wc  умеет считать не только строки и слова, но и байты, содержащиеся в файле
4) ls размер тоже отображает
- - - -
196308  001-portwine_dep.pfs нужно с помощью grep (или sed) вырезать из этой строки только размер и преобразовать в число - подскажите как это можно сделать
попробуйте:
stat -c %s 001-portwine_dep.pfs
имхо это проще, короче и grep (или sed) не нужны тут
« Последнее редактирование: 03 Ноябрь 2018, 08:46:00 от k0l0p0k »
1.пень G2020,8Gb,Radeon RX460 (Debian+openBox+LXPanel)
2.нетбук  Samsung N145 (Debian+openBox+LXPanel, ddr01)

Оффлайн Neyel

  • Ветеран
  • *****
  • Сообщений: 1548
  • Репутация: +28/-0
  • Автор темы
Начал писать потихоньку скрипт. Уже возникли вопросы - вот код:
Код
source_dir=/lib64
output_dir=""
cut_volume=""
out_name_dir=""
Volume_global=0

mv_file_move(){
array=($(ls -R $source_dir))
for filename in ${array[@]}
do
#Если это не имя файл а имя каталога (строка заканчивается на ":")
if [ $(echo "$filename" | grep ":$") ]
then
#Убрать двоеточие в конце имени каталога
prefix_dir=$(echo "$filename" | sed 's/:$//')
#Убрать source_dir в начале имени каталога
prefix_dir=$(echo "$prefix_dir" | sed 's|'$source_dir'||')
fi
done
}
mv_file_move
Можно ли это:
Код
#Убрать двоеточие в конце имени каталога
prefix_dir=$(echo "$filename" | sed 's/:$//')
#Убрать source_dir в начале имени каталога
prefix_dir=$(echo "$prefix_dir" | sed 's|'$source_dir'||')
сделать встроенными средствами shell а не использовать sed (влияет на время выполнения скрипта)?

Оффлайн Neyel

  • Ветеран
  • *****
  • Сообщений: 1548
  • Репутация: +28/-0
  • Автор темы
Написал вроде:
Код
source_dir=/home/live/lib
output_dir=/home/live/lib_cut
cut_volume=200000000
out_name_dir=
Volume_global=0
Volume_total=0
Dlina=0
Dlina_global=0

mv_file_move(){
array=($(sudo ls -R $source_dir))
Dlina=${#array[@]}
Volume_global=0
first_file=1
Volume_total=0
for filename in ${array[@]}
do
#Если это не имя файл а имя каталога (строка заканчивается на ":")
if [ $(echo "$filename" | grep ":$") ]
then
#Убрать двоеточие в конце имени каталога
prefix_dir=$(echo "$filename" | sed 's/:$//')
#Убрать source_dir в начале имени каталога
prefix_dir=$(echo "$prefix_dir" | sed 's|'$source_dir'||')
continue
fi
#Проверяем каталог ли filename
if [ -d $source_dir'/'$prefix_dir'/'$filename ]
then
#Если каталог - перейти к след витку цикла
continue
fi
Volume_file=`stat -c %s $source_dir'/'$prefix_dir'/'$filename`
Volume=$(($Volume_global + $Volume_file))
Volume_total=$(($Volume_total + $Volume_file))
sudo rm $out_name_dir'/'$prefix_dir'/'$filename
if [[ "$Volume" -lt "$cut_volume" || "$first_file" -eq 1 ]]
then
Volume_global=$Volume
sudo mv $source_dir'/'$prefix_dir'/'$filename $out_name_dir'/'$prefix_dir'/'
first_file=0
fi
echo  $source_dir'/'$prefix_dir'/'$filename
done
}
date1=$(date)
i=1
f=$(($cut_volume + $cut_volume))
Volume_total=$(($f+1))
while [ $Volume_total -gt $f ]
do
out_name_dir=$output_dir$i
mkdir $out_name_dir
sudo cp -r --attributes-only $source_dir'/'* $out_name_dir
mv_file_move
if [ $i -eq 1 ]
then
Dlina_global=$Dlina
fi
i=$((i+1))
done
out_name_dir=$output_dir$i
mkdir $out_name_dir
sudo mv $source_dir'/'* $out_name_dir
date2=$(date)
echo $Dlina_global
echo $date1
echo $date2

Результаты теста - Папка /usr/lib из пра-ролл 1806(перед запуском скопировал её в /home/live/, так как файлы из исходной папки перемещаются) - объём 1.3G, кол-во файлов ~17000, резал на куски по 200Мб:
Время старта скрипта - 09:11:32
Время окончания - 09:39:14
Кол-во кусков - 7
« Последнее редактирование: 08 Ноябрь 2018, 09:58:23 от Neyel »

Оффлайн midnighter

  • Ветеран
  • *****
  • Сообщений: 436
  • Репутация: +15/-0
сделать встроенными средствами shell
find -type d
Не подойдёт?

Оффлайн Neyel

  • Ветеран
  • *****
  • Сообщений: 1548
  • Репутация: +28/-0
  • Автор темы
find -type d
Не подойдёт?
Спасибо интересный вариант

Оффлайн Neyel

  • Ветеран
  • *****
  • Сообщений: 1548
  • Репутация: +28/-0
  • Автор темы
Переделал скрипт:
Код
source_dir=/home/live/lib
output_dir=/home/live/lib_cut
cut_volume=200000000
out_name_dir=
Volume_global=0
Volume_total=0
Dlina=0
Dlina_global=0

mv_file_move(){
array=($(sudo find $source_dir |sed 's|'$source_dir'||'))
Dlina=${#array[@]}
Volume_global=0
first_file=1
Volume_total=0
for filename in ${array[@]}
do
#Проверяем каталог ли filename
if [ -d $source_dir'/'$filename ]
then
#Если каталог - перейти к след витку цикла
continue
fi
Volume_file=`stat -c %s $source_dir'/'$filename`
Volume=$(($Volume_global + $Volume_file))
Volume_total=$(($Volume_total + $Volume_file))
sudo rm $out_name_dir'/'$filename
if [[ "$Volume" -lt "$cut_volume" || "$first_file" -eq 1 ]]
then
Volume_global=$Volume
sudo mv $source_dir'/'$filename $out_name_dir'/'$filename
first_file=0
fi
echo  $source_dir'/'$filename
done
}
date1=$(date)
i=1
f=$(($cut_volume + $cut_volume))
Volume_total=$(($f+1))
while [ $Volume_total -gt $f ]
do
out_name_dir=$output_dir$i
mkdir $out_name_dir
sudo cp -r --attributes-only $source_dir'/'* $out_name_dir
mv_file_move
if [ $i -eq 1 ]
then
Dlina_global=$Dlina
fi
i=$((i+1))
done
out_name_dir=$output_dir$i
mkdir $out_name_dir
sudo mv $source_dir'/'* $out_name_dir
date2=$(date)
echo $Dlina_global
echo $date1
echo $date2
Тест с той же папкой -
Время запуска - 18:46:32
Время окончания - 19:01:55
-15 мин вместо 28 мин в первоначальном варианте  8)