PDA

Просмотр полной версии : Сила shell'ов


tmp0000
29.05.2007, 01:06
Вот написал скриптик:

#/bin/bash
# Script for cleaning old Debian packaged
# Author: Igor Pellinen (Russia) aka Igron aka tmp0000

# First, create file with Packages
dpkg-scanpackages . /dev/null > Packages 2>/dev/null

# Make temporary directory
mkdir temp_dir_with_new_packages

# Move actual files to temporary directory
for i in `awk '/^Filename:/ {print $2}' Packages`; do test -f $i && mv $i ./temp_dir_with_new_packages/; done

# Delete old Debian packages, they are in current directory
rm -f ./*.deb

# Now, after deleting old packages, we must back actual packages back to the current directory:
cd ./temp_dir_with_new_packages/
for i in *.deb; do mv $i ../; done
cd ../

# Remove temporary directory and packages files
rmdir temp_dir_with_new_packages
rm Packages

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

Как можно улучшить скорость работы скрипта?

Frosty
29.05.2007, 14:59
Не прокатит такой вариант:в очищаемой папке создать файлик old-debs и при нахождении старого пакета записать в него remove /path/to/old/deb/ и интер :) и так по циклу, а потом просто запустить этот скрипт :) Или бред?

rmn
29.05.2007, 16:46
#!/bin/bash

dpkg-scanpackages . /dev/null > Packages 2>/dev/null
ls -1 ./*.deb | sort > old.list
awk '/^Filename: / {print $2}' Packages | sort > new.list
diff {old,new}.list | grep '^< ' | sed 's/^< //' | xargs rm -f
rm -f {old,new}.list

так лучше ? :)

greiv
29.05.2007, 17:36
Вот написал скриптик:

#/bin/bash
# Script for cleaning old Debian packaged
# Author: Igor Pellinen (Russia) aka Igron aka tmp0000

# First, create file with Packages
dpkg-scanpackages . /dev/null > Packages 2>/dev/null

# Make temporary directory
mkdir temp_dir_with_new_packages

# Move actual files to temporary directory
for i in `awk '/^Filename:/ {print $2}' Packages`; do test -f $i && mv $i ./temp_dir_with_new_packages/; done

# Delete old Debian packages, they are in current directory
rm -f ./*.deb

# Now, after deleting old packages, we must back actual packages back to the current directory:
cd ./temp_dir_with_new_packages/
for i in *.deb; do mv $i ../; done
cd ../

# Remove temporary directory and packages files
rmdir temp_dir_with_new_packages
rm Packages

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

Как можно улучшить скорость работы скрипта?

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

rmn
29.05.2007, 17:41
greiv, если бы он мог это сделать, то не заморачивался бы с написанием скриптов. :) Вообще, чтобы "вкурить" что он хочет автоматизировать, надо примерно знать как устроены и создаются репозитории debian/ubuntu и как там нумеруются версии пакетов.

greiv
29.05.2007, 18:34
rmn, а ты внимательно прочитай, что он в скобках написал - ...туда перемещаются нужные (актуальные) пакеты. Т.е. все же он их различает актуальные-то. Или он просто выразился не правильно.

rmn
29.05.2007, 18:44
greiv, я внимательно читал, более того - этой фигней занимался уже.

Есть каталог, в него навалена куча deb-пакетов различных версий, например, foo 0.40, foo 0.41, foo 0.41 backported. Пакетов для простоты - 1000 штук по 3-4 версии каждого.
Из них в каталоге нужно оставить только "актуальные" пакеты (вроде foo 0.41).

dpkg-scanpackages, грубо говоря, выдаёт список "актуальных" пакетов. Задача сводится к тому, чтобы из начального списка вычленить неактуальные, используя шелл.

greiv
29.05.2007, 20:04
rmn, ну цель-то понятна=), раз dpkg-scanpackages такой хороший, что выплевывает список "актуальных" пакетов, то зачем нужна свистопляска с отдельными директориями и перемещениями по тысячу раз... как будто неактуальные нельзя замочиь в том же каталоге

rmn
29.05.2007, 21:13
greiv, мне не совсем понятно, что ты предлагаешь. Шелл-сценарий для решения задачи в студию. :)

tmp0000
29.05.2007, 21:20
diff {old,new}.list | grep '^< ' | sed 's/^< //' | xargs rm -f
так лучше ?
Вроде да, я это пытался сделать, но как-то "ниасилил".. :(

Frosty
29.05.2007, 21:31
dpkg-scanpackages . /dev/null > Packages 2>/dev/null
ls -1 *.deb | sort > old.list
awk '/^Filename: / {print $2}' Packages | sort > new.list
diff {old,new}.list | grep '^< ' | sed 's/^< //' | xargs rm -f
rm -f {old,new}.list

так лучше ? :)Нипаешт :) закоим то создает новый Packzges.gz а пакетов старых не потирает :)

rmn
29.05.2007, 21:34
Frosty, опять напилсо. попробуй его с утра запустить. :]

tmp0000
29.05.2007, 21:34
Frosty, опять напилсо. попробуй его с утра запустить. :]
+1!!! :D :D :D

Frosty
29.05.2007, 21:59
Frosty, опять напилсо. попробуй его с утра запустить. :]Дануна, я закинул скриптв папку с архивами, запустил, он нахреначил мне новый Packages.gz, о чем и написал в консоли с подробным выводом списка пакетов, которые он включил, а файл gstreamer0.10-plugins-ugly_0.10.4-0ubuntu2_i386, лежащий рядом с gstreamer0.10-plugins-ugly_0.10.5-0ubuntu2_i386 не похерил...

rmn
30.05.2007, 13:04
Frosty, дык .gz надо развернуть предварительно. Либо прямо в скрипте изменить строку так:

zcat Packages.gz | awk '/^Filename: / {print $2}' | sort > new.list

Добавлено через 14 часов 31 минуту
Frosty, все-таки решил проверить на себе код ;) чтобы 100% работало без собственноручных доводок, нужно подправить строку
ls -1 ./*.deb | sort > old.list

Frosty
30.05.2007, 14:25
полностью от начала и до конца выложи скрипт, а то опять тренироваца не хочется :)

tmp0000
30.05.2007, 15:55
полностью от начала и до конца выложи скрипт, а то опять тренироваца не хочется
Да, я тоже себе кое-что убил :(

rmn
30.05.2007, 16:04
код (http://forum.battlefox.ru/showthread.php?p=123990#post123990)
должно работать :) но проверять сейчас времени нет.

Frosty
30.05.2007, 21:12
код (http://forum.battlefox.ru/showthread.php?p=123990#post123990)
должно работать :) но проверять сейчас времени нет.Опять мимо :)


frosty@frosty-desktop:~/Desktop/неозаглавленная папка$ sudo sh "/home/frosty/Desktop/неозаглавленная папка/clean"
diff: пропущен операнд после `{old,new}.list'
diff: Попробуйте `diff --help' для получения более подробного описания.
Но пакеты хотя бы разграничивает:
./gstreamer0.10-plugins-ugly_0.10.4-5_i386.deb
./gstreamer0.10-plugins-ugly_0.10.5-0ubuntu2_i386.

./gstreamer0.10-plugins-ugly_0.10.5-0ubuntu2_i386.

rmn
30.05.2007, 21:33
Frosty, скрипт написан на bash, а ты его запускаешь через sh. RTFM :)

Frosty
30.05.2007, 21:52
Все, работает, идеально ;)

Frosty
02.06.2007, 12:01
Хех, запустил скрипт rmn'a в папке с пакетами-моментальный Shift+Delete всей папки, смешно блин, видимо придеца опять выкачивать пару часов все архивы :)
Скрипт удаляет все.deb

rmn
02.06.2007, 16:34
Frosty, да-да, деструкция - наше фсё. :]
переделай скрипт, чтобы он не удалял, а перемещал пакеты в отдельный каталог.

Frosty
02.06.2007, 17:18
Если запукать скрипт через консоль из сухого и темного места, то все работает нормально, а ели из папки с пакетами, то приходица качать заново :)

tmp0000
03.06.2007, 01:01
Скрипт для массового переименования файлов с неправильными названиями
#/bin/bash
#Script that renames deb-packages that have bad filenames.
#Author: Igor Pellinen (Russia) aka Igron aka tmp0000 && Vadim Gusev (Russia) aka Frosty

#First we do a textfile that contains wrong filenames
find . -name '*%3a*' > wrong.names

#Rename files, mask [0-9]%3a is changed to nothing
for i in `grep %3a wrong.names`; do mv $i `echo $i | awk '{gsub("[0-9]%3a","");print }'` ; done

#Remove temporary textfile
rm wrong.names

#All done. What are waiting to see here? :)

dotpack
19.08.2007, 22:44
Подскажите, пожалуйста, необходимо для определённой директории сделать следующее:
- всем каталогам присвоить права 755
- всем файлам присвоить права 644

rmn
20.08.2007, 19:13
dotpack,
find /определенная/директория/ -type d -exec chmod 755 {} \;
find /определенная/директория/ -type f -exec chmod 644 {} \;

tmp0000
03.10.2007, 21:18
Возник вопросец: вывести все директории в текущей дире.
for i in *; do test -d $i && echo $i; done
выдает в некоторых строках: bash: test: слишком много аргументов
Это нужно товарищу в дальнейшем для аналога Denver под linux (да, знаю, это абсурдно звучит)

NOboDy
03.10.2007, 21:24
for i in *; do test -d $i && echo $i; done
Видимо дело в этом:

for i in *; do test -d "$i" && echo $i; done

rmn
03.10.2007, 21:49
золотое правило шелл-программинга - кавычить переменные. Во избежание.

ArcFi
16.04.2008, 19:11
Недавно пришлось переустанавливать систему и, чтобы потом не перекачивать заново 2,5 Гб, решил забекапить кэш, предварительно почистив его от пакетов старых версий.
К сожалению, aptitude autoclean удаляет старые пакеты, даже если они находятся в количестве одной версии, поэтому решил было использовать dpkg-scanpackages, как показано несколькими постами выше, немного оптимизировав код:
dpkg-scanpackages archives 2>&1 | grep -e '^ !.*is repeat;' | \
grep -o -e 'archives\/.*\.deb' | while read
do
sudo rm -v "${REPLY}"
done
Предполагаю, что кусок grep -e '^ !.*is repeat;' | grep -o -e 'archives\/.*\.deb' можно было бы заменить чем-то более элегантным...

И всё-таки, dpkg-scanpackages работает достаточно медленно, к тому же требует установки дополнительных пакетов, поэтому немного поразмыслив, написал ещё 1 сценарий:
ls -1 archives/*.deb | while read
do
test "${REPLY%%_*}" == "${PREV%%_*}" && sudo rm -v "${PREV}"
PREV="${REPLY}"
done

Возможно, что быстрый интернет ещё не всех настиг, и кому-то этот скриптик может пригодиться. ;)

Elwen
30.09.2008, 21:31
Вот такая задача:
Находится с помощью поиска (find) перечень неких каталогов, и необходимо подсчитать количество этих каталогов (с помощью команды wc) и вывести этот перечень на экран вместе с их количеством. Реально ли это сделать? По отдельности то всё работает )

rmn
30.09.2008, 21:52
ну, если "в лоб", то так
list="`find . -type d критерии поиска неких каталогов`"; \
echo "$list"; echo "$list" | wc -l

Elwen
30.09.2008, 22:22
rmn, не работает ) echo "$list" просто печатает собственно строку find блаблабла, ито без этого - \

rmn
30.09.2008, 22:26
Mornis, первый аргумент у find - корневой каталог поиска. В примере это текущий каталог (ему соответствует точка в шелле). Соответственно, точку надо заменить на каталог, о котором идёт речь в задании. Например, корневой /.

Во-вторых, критерии поиска тоже нужно сформулировать согласно синтактису команды find. Критерии поиска мне не ведомы. ;)

В-третьих, важен порядок, тип и кол-во кавычек. Шелл к этому чувствителен. :) Если всё это в порядок привести, то работать должно.

Elwen
30.09.2008, 22:30
rmn, во первых, я додумалась до того чтобы написать в поиске всё что нужно :) во вторых всё остальное ввела так же как у вас, но не работает ) кстати другого способа нет? ато можно ещё два раза поиск написать, то же самое будет

rmn
30.09.2008, 22:33
Mornis, какой шелл? версия? Вообще, лучше всё это сразу приводить. И задание дословно, и команда, которая в шелле исполнялось. Иначе разговор слепого с глухим получается.

InS7
30.09.2008, 22:48
версия там:

/bin/bash --help
GNU bash, version 3.1.17(1)-release-(i586-suse-linux-gnu)


у меня работает

list="`find /home -type d `";echo "$list"; echo "$list" | wc -l

а так

user@xxx:~> list="`find ~ -type d `";echo "$list"; echo "$list" | wc -l
list="`find ~ -type d `";echo "$list"; echo "$list" | wc -l
find ~ -type d
^C

не хочет

Добавлено через 2 минуты
ps. -maxdepth 1 добавь а то там где ты ищещь запаришься искать ;)

tmp0000
05.03.2009, 13:36
В последнее время только и занимаюсь тем, что качаю клипы с трубы.

Накидал скриптик для автоматического получения названия песни с трубы и переименования файлов.
#!/bin/bash
# ver. 0.1.0
# Script for collecting info from truba videos and rename files
# Author: Igor Pellinen <igronus[at]gmail[dot]com>
# Licence: GPL3+

# Directories
CLIPS_DIRECTORY="/home/igron/newclips/"

# Log file
LOG_DIRECTORY="/home/igron/"
LOG_FILE=".truba-parser.log"

# Create a new log file if it doesn't exist
cd "$LOG_DIRECTORY"
[ -e "$LOG_FILE" ]
if [ $? -eq 1 ]; then
echo "It seems like log file does not exist, creating..."
touch "$LOG_FILE"
fi

# Adding start time to log
echo "`date` Truba-parser started" >> "$LOG_DIRECTORY"/"$LOG_FILE"

# Start process
cd "$CLIPS_DIRECTORY"
for file_name in *
do
# File extension
extension=`echo ${file_name##*.}`

# File name without extension
file_short_name=`echo ${file_name%.*}`

# Get html file from truba
wget "http://truba.karelia.ru/video.php?id=$file_short_name" -O temp.file

# Parse info from html file
string=`cat temp.file | sed '1,/<head>/d' | sed '2,/<\/html>/d'`
string_utf=`echo $string | iconv -f koi8-r -t utf8`
length=`echo ${#string_utf}`
new_length=`echo "$length-15" | bc`
new_name=`echo ${string_utf:7:$new_length}`
new_full_name=$new_name"."$extension

# Log and process rename
echo "Renaming $file_name to $new_full_name..." >> "$LOG_DIRECTORY"/"$LOG_FILE"
mv "$file_name" "$new_full_name"

# Removing temporary html file
rm temp.file
done


# Adding end time to log
echo "`date` Truba-parser finished" >> "$LOG_DIRECTORY"/"$LOG_FILE"
Схема такая: URL клипов находится в файле, клипы льются по списку в каталог $CLIPS_DIRECTORY wget'ом, после чего данный скрипт их переименовывает как надо.

PS. No warranty, just idea. Use at your own risk.

NameLess
24.12.2009, 22:34
Люди нужна помощь в переделывание скрипта.
есть такой скрипт
#!/bin/bash
while read A TAIL
do
echo $A
done|sort|uniq -c|sort -nr|while read A TAIL
do
echo $TAIL -$A
done


нужно его переделать вот в это:

Системный журнал Linux содержит записи в следующем формате:
дата время хост демон[pid]: сообщение
Пример журнала:
Sep 25 16:55:00 plasma CROND[4014]: bla-bla-bla
Sep 25 16:55:07 plasma CROND[4012]: bla-bla-bla
Sep 25 16:55:23 plasma CROND[4035]: bla-bla-bla
Sep 25 16:55:00 plasma mgetty[4013]: bla-bla-bla

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

Пример:
$./myscrpt.sh </var/log/messages
CROND: 4014, 4012, 4035
mgetty: 4013

а то первый осилил а второй пока не могу.

NOboDy
26.12.2009, 15:44
NameLess,
Смотри тут 98605.
Тока учти, оно писано для знакомого пару лет назад и его вроде уже сдавали. :)

NameLess
27.12.2009, 23:54
NameLess,
Смотри тут 98605.
Тока учти, оно писано для знакомого пару лет назад и его вроде уже сдавали. :)

Спасибо. Я немного допилил, чтоб уникальность очереди соблюдалось!Ты меня спас от egrep!=)))