1

Доброе время суток уважаемые форумчане,  прошу дать совет или же направить на путь истины.
Суть в том что необходимо написать Скрипт sh который будет копировать файлы с папки в папку с одним но.
Исходныe файлы называются  d.1.du   w.1.su  s.1.rf
лежат в /home/ скопировать нужно в /home/1/
Но скопировать нужно с добавлением даты и сохранением последних строк оригинального файла
Т.e  файлы после копирования должны иметь вид

20120803_1.du   20120803_1.su.  20120803_1.rf.   Просто добавив в процессе копирования дату и обрезать название в начале.

2

#!/bin/bash
# Путь к каталогу с файлами
SRC_DIR="${1}"
# Количество скопированных строк.
NUMBER_STRING="2"

mkdir -p "${SRC_DIR}/1"

for i in $(ls "${SRC_DIR}");
do
        [ -f "${SRC_DIR}/${i}" ] && tail -n ${NUMBER_STRING} "${SRC_DIR}/${i}" >  "${SRC_DIR}/1/$(date +%Y%m%d)_${i#*.}"
done

P.S. В качестве аргумента скрипту передаётся путь к целевому каталогу, в вашем случае /home.
Скрипт без «изысков», поэтому должен находиться вне вашего каталога /home

Был, был и весь вышел...

3

Спасибо, скрипт работает а если нужно не копировать а перемещать файлы  т.е не оставлять их в /home/

4

sinxron пишет:

Спасибо, скрипт работает а если нужно не копировать а перемещать файлы  т.е не оставлять их в /home/

#!/bin/bash
SRC_DIR="${1}"
NUMBER_STRING="2"
mkdir -p "${SRC_DIR}/1"
 
for i in $(ls "${SRC_DIR}");
    do
        [ -f "${SRC_DIR}/${i}" ] && tail -n ${NUMBER_STRING} "${SRC_DIR}/${i}" >  "${SRC_DIR}/1/$(date +%Y%m%d)_${i#*.}"
         rm -f "${SRC_DIR}/${i}" > /dev/null 2>&1
done

Как-нибудь так, но всё это пишется «на коленке», так что возможны огрехи. bx

Был, был и весь вышел...

5 (06.08.2012 08:44:04 отредактировано sinxron)

не пойму в чём проблемма при перемещении файлов размер файлов меняется были от 870кб до 15мб стали намного меньше и почти одинаковые. внутри файлов вместо кучи данных только первые две строчки после выполнения скрипта  ac

6

sinxron пишет:

не пойму в чём проблемма при перемещении файлов размер файлов меняется были от 870кб до 15мб стали намного меньше и почти одинаковые. внутри файлов вместо кучи данных только первые две строчки после выполнения скрипта  ac

sinxron пишет:

Но скопировать нужно с добавлением даты и сохранением последних строк оригинального файла

Разумеется, файлы будут меньше. Если нужно обычное переименование, то

[ -f "${SRC_DIR}/${i}" ] && tail -n ${NUMBER_STRING} "${SRC_DIR}/${i}" >  "${SRC_DIR}/1/$(date +%Y%m%d)_${i#*.}"
         rm -f "${SRC_DIR}/${i}" > /dev/null 2>&1

надо заменить на

[ -f "${SRC_DIR}/${i}" ] && mv "${SRC_DIR}/${i}"  "${SRC_DIR}/1/$(date +%Y%m%d)_${i#*.}"
Был, был и весь вышел...

7 (07.08.2012 13:05:36 отредактировано sinxron)

Спасибо!Отлично работает, Ещё хотел бы узнать пару вопросов если возможно. У меня исходные файлы лежат теперь не в оной папке а 6-ти разных т.е /home/1/  /home/2/   /home/3/    /home/4/   /home/5/   /home/6/  соответственно перемещаю их в /home/base/ как лучше сделать чтоб не писать постоянно для каждой папки всю процедуру копирования да и возможно ли?
например скрипт зашёл в папку 1 выполнил [ -f "${SRC_DIR}/${i}" ] && mv "${SRC_DIR}/${i}"  "${SRC_DIR}/1/$(date +%Y%m%d)_${i#*.}"
потом во 2 папку 3 4 5 6  что бы код не повторять для каждой папки можно ли такое сделать?
Ну и второй вопрос все файлы имеют в первой строке дату можно ли вместо даты $(date +%Y%m%d) подстовлять дату из файла
по принципу

head -1 файл | cut -c 27-34

первая строчка в файле  353763 3647 3900-_370000000012_08_03_39800472.    это дата > 12_08_03

8

sinxron пишет:

как лучше сделать чтоб не писать постоянно для каждой папки всю процедуру копирования да и возможно ли?

Возможно. Часть скрипта, отвчечающую за переименование и перемещение, оформить функцией. Далее эту функцию запустить в цикле for i in .... fi для указанной последовательности каталогов.

sinxron пишет:

Ну и второй вопрос все файлы имеют в первой строке дату можно ли вместо даты $(date +%Y%m%d) подстовлять дату из файла
по принципу

head -1 файл | cut -c 27-34

Можно, но вместо cut лучше использовать sed или awk.

Был, был и весь вышел...

9

ЧТо то на подобии этого head -1 file | sed 's/^.\{26\}\([0-9]\{8\}\).*$/\1/'

10

sinxron пишет:

ЧТо то на подобии этого head -1 file | sed 's/^.\{26\}\([0-9]\{8\}\).*$/\1/'

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

Был, был и весь вышел...

11 (07.08.2012 14:42:28 отредактировано sinxron)

да

2787675D 4 5643HTS312-08-0300-00-0000-0012-08-0300-00-000

дата 12-08-03 после символов......HTS3 (но бывает и после HLQ2 это меняется)но дата имеет фиксированную позицию во всех файлах , необходимо брать её и загонять вместо $(date +%Y%m%d)

12

Если позиция постоянная, то можно и cut, как вы предлагали сразу.

Был, был и весь вышел...

13

а как head -1 файл | cut -c 27-34  подставить вместо $(date +%Y%m%d) ?

14

$(head -1 файл | cut -c 27-34)

только номера полей точнее подберите, вроде бы должно быть 29-36

Был, был и весь вышел...

15

sinxron пишет:

первая строчка в файле  353763 3647 3900-_370000000012_08_03_39800472.    это дата > 12_08_03

sinxron пишет:

2787675D 4 5643HTS312-08-0300-00-0000-0012-08-0300-00-000

Позиция даты в строках различается.

Был, был и весь вышел...

16

все строки такие 2787675D 4 5643HTS312-08-0300-00-0000-0012-08-0300-00-000   в шапке набрал от балды

17 (07.08.2012 20:34:44 отредактировано sinxron)

Сделал так надеюсь верно  [ -f "${SRC_DIR}/${i}" ] && mv "${SRC_DIR}/${i}"  "${SRC_DIR}/1/$(head -1 ${SRC_DIR}/${i} | cut -c 19-26)_${i#*.}"  работает

12-08-03

18 (16.08.2012 08:33:00 отредактировано sinxron)

Для упрощения кода сделал так функция берёт файлы с /home/1 /home/2 и так до /home/5 (Переменная $d внутри цикла содержит текущую директорию из перебираемых)и кидает их в папку /home/base/ под именами FILE1 FILE2......FILE5


#!/bin/bash

for d in /home/[1-5];
do
for f in "$d"/*
  do
    [ -f "$f" ]  && mv "$f" "/home/base/FILE$(basename "$d").${f#*.}"
done
done

вырезал дату с первой строчки по позиции  но позиции оказались разные  соответственно использую sed

sed -n '1{s|^.*\([0-9]\{2\}-[0-9]\{2\}-[0-9]\{2\}\).*$|\1|;p}'

Как подружить эти 2 пункта ??? что бы новый код так же вырезал дату с файлов?

19

sinxron пишет:

Как подружить эти 2 пункта ??? что бы новый код так же вырезал дату с файлов?

DATE=$(sed бла-бла-бла)
mv "$f" "$DATE$f"
Карусель разнесло по цепочке за час
Всех известий — конец
Да, весна началась!
(всё к лицу подлецу, как родному отцу, не рассказывай, батя, и так всё пройдёт)

20

Спасибо, но что то не выходит  у меня ac  после добовления строчки всё остальное не выполняется. Прошу не пинать сильно т.к новичек в этом деле.

DATE=$(sed -n '1{s|^.*\([0-9]\{2\}-[0-9]\{2\}-[0-9]\{2\}\).*$|\1|;p}')

#!/bin/bash

for d in /home/[1-5];
do
for f in "$d"/*
  do
    [ -f "$f" ]  && mv "$f" "/home/base/FILE$(basename "$d").${f#*.}"
done
done

21

sinxron пишет:

Спасибо, но что то не выходит  у меня ac  после добовления строчки всё остальное не выполняется. Прошу не пинать сильно т.к новичек в этом деле.

DATE=$(sed -n '1{s|^.*\([0-9]\{2\}-[0-9]\{2\}-[0-9]\{2\}\).*$|\1|;p}')

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

Карусель разнесло по цепочке за час
Всех известий — конец
Да, весна началась!
(всё к лицу подлецу, как родному отцу, не рассказывай, батя, и так всё пройдёт)

22

#!/bin/bash

for d in /home/[1-5];
do
for f in "$d"/*
  do
    [ -f "$f" ]  && mv "$f" "/home/base/FILE$(basename "$d")$(head -1 $f | cut -c 27-34).${f#*.}"
done
done

Вот так всё работает если дата на фиксированной позиции , а если нет ...... а вот SED так и не могу запихнуть. читает только последнюю дату в файле .

строчка
00000000012-12-12000000000012-11-11000000000012-10-10000000000       SED выдаёт 12-10-10

а если просто запустить SED работает. Не хочет работать почемуто этот кусок .*$|\1|;p}')  из SED

23

sinxron пишет:

строчка
00000000012-12-12000000000012-11-11000000000012-10-10000000000       SED выдаёт 12-10-10

ну и нормально. А вы что хотели? Читаем про жадность.

Карусель разнесло по цепочке за час
Всех известий — конец
Да, весна началась!
(всё к лицу подлецу, как родному отцу, не рассказывай, батя, и так всё пройдёт)

24

Спасибо за хороший MAN

25

drBatty пишет:

.

доктор, не нашел в вашем мануале описания различия между конвейером и опцией

sed -e ... -e ... -e ...    VS    sed ... | sed ... | sed ...

почему sed ведет себя по разному в некоторых случаях?

может как нибудь обновите мануальчик?

"Фирма Майкрософт не собирается поддерживать протокол TCP/IP в своих OS" 1993 (c) Билл Гейтс
"Мы изобрели новый протокол передачи данных, мы назвали его TCP/IP" 1995 (c) Билл Гейтс

26

moshell пишет:

почему sed ведет себя по разному в некоторых случаях?

а почему он должен себя одинаково вести о_О

sed -e -e — все скрипты выполняются в одном контексте, а sed | sed — совершенно независимо.

 Консоль:

$ echo qwe | sed -e x -e x
qwe
$ echo qwe | sed -e x | sed -e x

[оффтоп] drBatty, рад видеть...

95% процентов проблем находятся между клавиатурой и стулом.

27

moshell пишет:

доктор, не нашел в вашем мануале описания различия между конвейером и опцией

потому-что это не имеет никакого отношения к sed.
Опция -e вообще не имеет никакого смысла (кроме использования команд, у которых имеется параметр - имя файла, или иная строка. Но даже в этом случае, я предпочитаю использовать многострок или файл-скрипт)

moshell пишет:

почему sed ведет себя по разному в некоторых случаях?

ну потому-что sed -e x -e x эквивалентно sed 'x;x', т.е. для каждой строки выполняются две команды последовательно. В данном случае,

1. обменивается буфер и область удержания
2. обменивается область удержания и буфер

Очевидно, результат от этого не меняется.

Если вы запускаете ДВЕ команды sed 'x' | sed 'x', то
1. обменивается исходная строка и ПЕРВАЯ область удержания (из первой команды)
2. обменивается ВТОРАЯ область удержания, с ПЕРВОЙ областью, которая поступила из конвейера.

Результат первого случая:

$ echo "a
b
c
d" | sed 'x;x'
a
b
c
d

(нет изменений)

результат второго:

$ echo "a
b
c
d" | sed 'x' | sed 'x'


a
b

(задержка на 2 строки - первая строка сначала уходит в первую область удержания, затем во вторую, а уж затем выходит из конвейера)

ЗЫЖ замечу, что конвейер намного дольше работает, хотя некоторые вещи без него не сделать. К примеру sed = выдаёт номер строки, но выдаёт его только наружу, потому поймать и обработать его можно лишь второй sed...

Карусель разнесло по цепочке за час
Всех известий — конец
Да, весна началась!
(всё к лицу подлецу, как родному отцу, не рассказывай, батя, и так всё пройдёт)

28

Fat-Zer пишет:

оффтоп] drBatty, рад видеть...

взаимно

Карусель разнесло по цепочке за час
Всех известий — конец
Да, весна началась!
(всё к лицу подлецу, как родному отцу, не рассказывай, батя, и так всё пройдёт)