LINUX.ORG.RU

Код для копирования случайных файлов и ограничение размера

 


0

1

Доброго времени суток! Нижайше прошу помощи гуру! Есть уже готовый код, который делает ls в папке, и копирует случайные файлы из этого списка в другую папку, но у меня возникли следующие вопросы: 1) Можно ли сохранить результаты запроса ls не в файл, а в переменную, и выбирать случайное значение оттуда? 2) Можно ли заставить скрипт после выполнения копирования каждого файла, проверять размер каталога, и остановиться по достижению заданного размера? Скажем мне нужно чтобы скрипт накопировал в каталог музыки, в случайном порядке, но чтобы папка не была больше 700 МБ(CD диск). Привожу код

#!/bin/bash
#Music_folder
mf=/mnt/h500gb/download/Music
echo "Определена папка источник это $mf"
ls $mf > ~/music.txt
fl=~/music.txt
dest=/mnt/h500gb/download/to_cd
echo "Определена папка назначения это $dest"
if [ -d $dest/ ]
	then
	echo "Папка $dest существует продолжаем"
	else
		echo "Папка $dest не существует, создаю"
		mkdir -pv $dest
	fi
# target_size
ts=702000
echo "Размер-цель $ts"
count=$(cat $fl | wc -l)
echo "Количество песен в источнике $count"
weight=$(du --total $dest)
echo "Вес источника $weight"
while [ "weight" != "$ts" ]
	do
		du --total $dest
		mp3=$(shuf -i 1-$count -n 1)
		echo "Номер для копирования $mp3"
		nomp3=$(head -n $mp3 $fl | tail -n 1)
		echo "Кандидат на копирование $nomp3"
			if [ -f "$dest/$nomp3" ]
				then
				echo "$dest/$nomp3 уже существует, следующий!"
				continue
			else
				echo "В папке назначения такого нет! Так и запишем!"
				rsync -avhu --progress --partial "$mf/$nomp3" "$dest/$nomp3"
				continue
				echo "$dest/$nomp3 скопирован! Дальше!"
			fi
			echo "Вес в пределах нормы"
			continue
done

Сохранить вывод в переменную и выбрать из него случайный элемент

list=$(ls)
head -$((${RANDOM} % $(wc -l <<< "${list}") + 1)) <<< "${list}" | tail -1

zolden ★★★★★ ()
Ответ на: комментарий от WorstPilot

Это местный фанат zsh, не обращай на него внимания. Детская травма от sh знаете ли.

IPR ★★★★★ ()
Ответ на: комментарий от WorstPilot

-$ ничего не значит, тут просто в параметры head подставляется выражение вычисленное в $()
<<< подаёт на вход команде слева строку справа
% - остаток от деления

от использования wc тут можно отказаться, но надо вспоминать синтаксис массивов в шелле, а мне некогда, меня мамка на ужин зовёт

zolden ★★★★★ ()

О, небо! Зачем так сложно?

Можно ли заставить скрипт после выполнения копирования каждого файла, проверять размер каталога, и остановиться по достижению заданного размера? Скажем мне нужно чтобы скрипт накопировал в каталог музыки, в случайном порядке, но чтобы папка не была больше 700 МБ(CD диск).

ls | sort -R | while read file && [ $(du -sm ../CD | awk '{print $1}') -lt 700 ]; do cp "$file" ../CD/; done
legolegs ★★★★★ ()
Последнее исправление: legolegs (всего исправлений: 1)
Ответ на: комментарий от legolegs

Но не будет ли такая строка копировать до переполнения лимита одним файлом? Ведь тогда дисочек он записать не сможет.

Bfgeshka ★★★★★ ()
Последнее исправление: Bfgeshka (всего исправлений: 1)
Ответ на: комментарий от legolegs

Позвольте, а разве тут есть рандомный порядок? Разве это не будет последовательным копированием?

WorstPilot ()
Ответ на: комментарий от legolegs

В любом случае, спасибо за ваш пример, не знал о такой возможности как рандомное сортирование списка. Вопрос, а не прервётся ли копирование если файл скоприровался частично, но указанный размер уже достигнут?

WorstPilot ()
Ответ на: комментарий от legolegs

Вместо ls лучше подставить выхлоп

find . -size -700M
Ну и маску применить по суффиксу имени или MIME. Тогда не нужно будет каждый раз du вызывать.

anonymous ()
Ответ на: комментарий от anonymous

А, понял, я ТЗ не правильно прочел.

ТС, для записи музыкальных архивов на DVD я сделал все намного проще: создал образ, в точности равный размеру DVD, подмонтировал его и копировал туда файлы. Как заполнялся, писал на диск.

Но этой чушью я давно перестал заниматься, т.к. есть торренты, а пару терабайт музыки на DVD не перекопируешь!

anonymous ()
Ответ на: комментарий от WorstPilot

Не прервётся. Результат всегда будет больше, чем 700мб. Надо либо брать объём с запасом, либо удалить лишний файл. Поскольку файлы могут быть очень разного размера сделать правильный алгоритм, который бы и максимально заполнял диск, и жестко выдерживал размер очень трудно, по сути это сводится к «задаче упаковки», которая аналитически не решаема за линейное время, да и случайному выбору противоречит.

legolegs ★★★★★ ()
Ответ на: комментарий от legolegs

Максимальное заполнение не есть цель, цель остановить копирование как только размер будет привышен или достигнут. А после удалить один лишний файл. В данном случае хотел лишь понять как сделать «горшочек больше не вари»)

WorstPilot ()

А че не так?

for file in `ls | sort -R | head -n 100`; do cp $file yourdir ; done

или не так?

for file in `find ./ -size +10M | sort -R | head -n 100`; do cp $file yourdir ; done
soomrack ★★★ ()
Ответ на: комментарий от legolegs

Ну так, в кавычки бери, echo это же просто заглушка, чтобы продемонстрировать, что работает.

ls | sort -R | head -n 100 | while read file; do stat "$file" ; done
soomrack ★★★ ()
Ответ на: комментарий от legolegs

На основе подсказок legolegs

Готовый код: Всем спасибо!


#!/bin/bash
sf=/mnt/h500gb/download/Music
echo "Папка источник $sf"
dest=/mnt/h500gb/download/to_cd
echo "Папка назначения $dest"
ts=702
ls $sf | sort -R | while read file && [ $(du -sm $dest | awk '{print $1}') -lt $ts ]
	do rsync -avhu --progress "$file" $dest
	echo "Размер папки назначения $(du -sm $dest | awk '{print $1}')"
done
if [$(du -sm $dest | awk '{print $1}') -gt $ts]
	then
	echo "Папка весит больше 702МБ, и не влезет в указанный размер! Удалю парочку лишних файлов..."
		ls $dest | sort -R | while read file && [ $(du -sm $dest | awk '{print $1}') -gt $ts ]
			do rm -v "$dest/$file"
		done
		echo "Мы закончили!"
	else
		echo "Папка нужного размера! Поздравляю!"
		echo "Мы закончили"
fi
exit
[code\]

WorstPilot ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.