LINUX.ORG.RU

перенос файлов из папки в папку

 , , ,


1

1

привет! появилась интересная задачка. пытаюсь понять как сделать скрипт переноса файлов цель

есть папка в которую попадают txt файлы разного размера. на данный момент происходит обычный move mv /opt/papka1/* /opt/papka2 откуда сервис все высасывает.

наткнулись на проблему если в файле много строк, он весит больше 1мб ломается сервис и все встает.

пытаюсь понять как написать скрипт который

будет забирать файлы которые не превышают 1мб из папки1 в папку2, все файлы которые превышают 1мб он будет разбивать на куски по строкам. чтоб в файле было не больше 10тыс строк. эти файлы можно переместить в папку3 где настроить crontab так чтоб он забирал 1 файл в 1 минуту. дабы не убить сервис в который может прилететь 100 файлов вместо 1 :-)

сижу уже день бьюсь в непонимании как это сделать.

на ум пришло такое решение. в crontab сделать вызов mv с 00.00 до 15.00

* 00-14 * * * mv /opt/papka1/*.txt /opt/papka1

а после 15.00 запускать такой вариант.

find /opt/papka1/* -size -100 -exec mv '{}' /opt/papka2 \;

а вот что делать с разбивкой пока не понимаю



Последнее исправление: plohish987 (всего исправлений: 7)

inotify. Например:

inotifywait -e close_write -r директория && mv […]

или, вместо mv, split с нужными параметрами. Но лучше (намного лучше) не костылить на баше и написать скрипт на нормальном языке (на вкус). Ещё лучше - чинить сервис чтобы не валился, если это возможно - не перекидывать текстовые файлы.

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

да это понятно что сервис чинить. уже отправили на доработку но это доработка и прочее.. сейчас нужен костыль который сможет исполнить хоть какую то защиту )

plohish987
() автор топика

Используй программы find, у неё есть параметр поиска по размеру, ищи файлы большего размера, чем твой пороговый размер и с ними производи действия с помощью split, всё можно уместить в пару строк, изучи параметр exec у find

Если надо разбивать по строкам, то split может и не поможет, можно попробовать в цикле head или tail, не знаю всех тонкостей split, может он тоже умеет по строкам

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

тонкостей split, может он тоже умеет по строкам

Не надо split путать с csplit. Вот csplit точно режет по строкам.

anonymous
()

Попробуй поставить на крон вот это:

#!/bin/bash
for i in $(find /origin/ -maxdepth 1 -name "*.txt"); do
    if [ $(wc -c < $i) -gt 1000000 ]; then
        filename=$(basename $i)
        split --lines=5000 $i /destination/"${filename%.*}_" --additional-suffix=".txt" --numeric-suffixes=1
        rm $i
    else
        mv $i /destination/
    fi
done

Разбивает по 5к строк

Так же учитывай, что find будет смотреть рекурсивно все каталоги от указанного вглубь, если нужно это регулировать, добавь параметр maxdepth, например -maxdepth 1, что бы четко указать, что интересуют только файлы в указанной директории.

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

спасибо! пока думал вертел. подкинули такую еще идейку

#!/bin/bash

MAX_LINES=10000
SRC_DIR=/opt/papka1 
TARGET_DIR=/opt/papka3

for i in $SRC_DIR/*.txt; do
    if [ ! -f $i ]; then break; fi
    LINES=`wc -l $i`
    if [ ${LINES% *} -gt $MAX_LINES ]; then
 csplit -ks -f$TARGET_DIR/${i%.*}_ $i $MAX_LINES {$((${LINES% *}/$MAX_LINES-1))}
 rm -f $i
    else
 mv -f $i $TARGET_DIR
    fi
done

но чет как то не хочет оно разбивать по 10 000 строк (((

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

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

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

А в целом это два идентичных куска кода, который просто используют чуть разные подходы.

У меня wc -c что бы посчитать байты, а у тебя wc -l для строк. Твой код оперирует константами, мой хардкодом (в случае костыля не критично имхо).

Ну и я использую обычный split, который имхо сильно читаемее :)

Еще, у тебя могут вылезти проблемы вот с этой конструкцией -f$TARGET_DIR/${i%.*}_

В реальных путях ты получишь что ни будь типа no such file or directory /opt/papka3/opt/papka1/file_aa

Именно по этому я сначала делаю basename.

Saivrem
()

Правильно - из папки в мамку, тупой вендузенок.

anonymous
()

Папка тебе ремня выдает, а файлы находятся в директории.

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

спасибо ) я твой скрипт впилил. потестил разными файлами, все взлетело. спасибо еще раз ))

а теперь внимание! вишинка на торт!!!

руководство сказало спасибо, но использовать это не будем!!! занавес (ノ°益°)ノ

говорит ты ж придумал запихать 2 шага в crontab этого достаточно.

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

Не парься :) Просто относись к этому как к новому опыту в свою копилку.

Рад был помочь.

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

ну подумать только, кто-то добровольно и бесплатно в 2021 году пишет портянки на баше

anonymous
()

если папки на одном диске mv должен просто переименовывать пути без копирования. Это происходит моментально при любом весе, потому что никакого реального «переноса» не происходит

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