LINUX.ORG.RU

Расфасовка файлов по количеству

 


0

2

Пускай дано множество файлов. Нужно брать первые N файлов, создавать для них каталог (0001 например) и переходить к следующим N файлов, так до тех пор, пока файлы не кончатся.

Можно ли по-простому написать какой-то shell-скрит для этого? Если да, то какие методы для этого лучше использовать.

В интерпретируемых языкх пока новичок, так что лучше либо шелл, либо сразу С.

★★★★★

Всё можно. Алгоритм ты сам почти целиком и описал:
* берёшь первые N имён файлов из вывода того же find
* ищешь каталог с максимальным номером, sort поможет
* создаёшь новый с номером на единицу больше
* перемещаешь первые N файлов в новый каталог
* повторяешь до нулевого вывода при поиске

manntes-live ★★★
()
Последнее исправление: manntes-live (всего исправлений: 1)

Общий алгоритм:

while <есть хоть один файл>
do
создать директорию
for x in $(find -type f | head -n1000)
do
mv $x <директория>
done
done

Допиливай.

staseg ★★★★★
()

Это уже третья или четвёртая тема с этой задачей на моей памяти. Колитесь, из какой она методички?

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

Да нет, просто бытовая задача, для себя.

Bfgeshka ★★★★★
() автор топика

Спасибо всем за маны и советы, кое-что наиндусил:

#!/bin/bash
testpath=~/images/test
num=100
Z=$(ls | wc -l)
dnum=1
until [ $Z -eq 0 ]
do
	mkdir $testpath/"$dnum"
		for x in $(find -type f | head -n$num)
		do
		mv $x $testpath/"$dnum"
		done
let dnum=$dnum+1
Z=$(ls | wc -l)
done
exit 0

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

наидусил

Отлично. А теперь воспользуемся Башем.

#!/bin/bash

# config
N=100
DIR="$HOME/images/test/"

set -e

cd "$DIR"
set *

while :; do
    TARGET="$((i++))"
    mkdir "$TARGET"
    mv "${@:1:$N}" "$TARGET"
    shift $N || break
done

Обратите внимание, что ситуация при которой среди подлежащих сортировке файлов имеются именованные 0, 1, 2 и т. д. никак не обрабатывается — добавьте их обработку по своему усмотрению.

Zmicier ★★★★★
()

Быдлокодеров-то собралось. Вот нормальный скрипт, отрабатывает за линейное время, не кладёт файлы в существующие директории.

#!/bin/bash
set -euo pipefail

target=${1:?"Usage: $0 <targed dir> [maxfiles]"}
maxfiles=${2:-1000}

dirn=0
filesn=$maxfiles
ls | while read FNAME; do
  if [ $filesn -eq $maxfiles ]; then
    filesn=0
    while true; do
      ((++dirn))
      dirname=$target/$(printf %.4d $dirn)
      if [ ! -d "$dirname" ] then break; fi
    done
    mkdir "$dirname"
  fi
  ((++filesn))
  mv "$FNAME" "$dirname/"
done
legolegs ★★★★★
()

так что лучше либо шелл, либо сразу С

Как жеж ты говном обходишься?

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

Ну и портянка, тут же mv, можно проще.

#!... -e
usage ...
lim=$1
dst=$2

while [ -n "$(ls)" ]
do
    : $(( i+=1 ))
    dir="$(printf "$dst/%04d" $i)"
    mkdir "$dir"
    ls | head -n $lim | xargs mv -t "$dir"
done
anonymous
()
Ответ на: комментарий от legolegs

«$(ls)»

Не включай дурачка, ниже сообщение.

Ты просто выкинул проверку на существование директорий

-e & mkdir => свалится если уже есть

Не зазнавайся, если бы оглядывался на твой код, тоже бы получилось малочитаемо :). Но фишка, конечно, в xargs.

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

Ну да, присметрелся к твоему find. Так уже норм.

Просто после нескольких неприятных случаев у меня аллергия на алгоритмы с O(N) по памяти.

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