Ru-Board.club
← Вернуться в раздел «Прикладное программирование»

» Shell scripts (sh, bash, zsh, tcsh)

Автор: ivanmara
Дата сообщения: 23.07.2008 18:27
Народ подскажите как получить имя файла без слешей в скрипте. допустим файл запускается из /usr/bin/ctest ... тогда переменная $0 получит значение /usr/bin/ctest а мне нужно получить именно имя файла без пути ... то есть просто ctest как бы сделать ?

Добавлено:
Разобрался. Пару вариантов(предполагаеться что нет аргументов коммандной строки после пути к файлу):
1. используем unix комманду basename
filename=`basename "$path_with_arg"`
echo $filename;

2. средствами самого bash:
filename=${path_with_arg##*/}
echo $filename;

смысл выражения ##:
${string##substring}
Удаление самой длинной, из найденых, подстроки $substring в строке $string. Поиск ведется с начала строки
где */ - любая последовательность символов включая /

Правильно обрабатывает случаи:
/usr/bin/test
./test
Автор: glebsts
Дата сообщения: 18.11.2008 10:19
Добрый день,
подскажите пожалуйста, как набор строк - результат обработки файла sed-ами и grepами - перевести в shell массив (declare -a ..)? Массив большой, поэтому перформанс критичен..
Спасибо.
Автор: glebsts
Дата сообщения: 03.12.2008 00:44
Мде, как-то здесь тихо.
Еще вопрос возник: создаю строковую переменную, которую потом хочу использовать как паттерн для грепа.
p1="a|b"
str="abc"

echo `echo ${str} | grep -E '${pl}'`
Есть мнение, что символ | как-то не по замыслу начинает использоваться.
Подскажите, как правильно сделать?
Автор: f_serg
Дата сообщения: 05.12.2008 08:26
glebsts

Цитата:
Подскажите, как правильно сделать?



Код: $ p1="a|b"
$ str="abc"
$ echo ${str} | grep -E "${pl}"
abc
$
Автор: Serhi_84
Дата сообщения: 08.12.2008 00:43
Здравствуйте.

Есть 2 сервера - локальный и удаленный (юниксовые). Необходимо сделать синхронизацию одной папки с подпапками. Собрал rsync, планируется, что данные будут передаваться с удаленной машины на локальную, то есть по идее rsync должен валяться на локальной машине. Накидал простенькую строчку:

rsync -aqz -e "ssh -pXXX" user@server:/remore_dir/ /local_dir/

запускаю - пишет ошибку. Пробую с параметром -vv - пишет не может найти rsync (хотя в скрипте путь был полностью прописан). Хорошо, кидаю файл в /usr/bin - все-равно такое же. Решил проверить на всякий случай, кинул rsync на удаленный сервак - скрипт заработал! Теперь первый вопрос - почему при такой передаче необходимо чтобы rsync находился на удаленной машине? По идее есть 2 варианта - либо rsync на удаленной - демон, либо он хранится на локальной машине. На удаленке демон мне не нужен. Неужели он должен валяться на обеих машинах?

Далее, при запуске скрипта у меня появляется строка для ввода пароля, пароль вввожу ручками, все синхронизируется. Вопрос второй - как в строчке скриптовой прописать пароль? Пробовал по-всякому:

rsync -aqz -e "ssh -pXXX" user:pass@server:/remore_dir/ /local_dir/ - не работает

rsync -aqz -e "ssh -pXXX" user@server:/remore_dir/ /local_dir/ < pass - не работает

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

Понимаю, что можно сделать все через ключи и делается это просто, но требуется реализация процедуры, описанной выше (если это вообще возможно сделать)

Заранее спасибо
Автор: Weinaum
Дата сообщения: 24.06.2009 22:38
В общем, решил настроить регулярный бекап по расписанию удаленной бд средствами mysql, так как заметил, что сторонние программы очень ненадежны - то там то тут ошибки...
Задача такая:
Находясь во freebsd - локальной машине, необходимо подключиться по ssh, соединиться с хостом удаленной базы - бд и сайт на разных хостах - после чего выполнить mysqldump и затем полученный дамп скопировать себе в папку. Нужно, чтобы все это дело последовательно обрабатывалось простым скриптом и было записано в крон - в принципе, все основное таким именно простейшим в одну строчку скриптом сделал, вышло где то так:

Цитата:
#!/bin/sh

BACKUPFILE=/home/user/dumps/db_`date +%H:%M_%d%m%y`.sql.gz

ssh user@mysite.com 'mysqldump -u dbuser -ppassword db_mydb -h dbhost | gzip' > ${BACKUPFILE}


Ну вот, в принципе, прописал в кроне и все работает. Имена специально хочу делать с датой и временем, и вот почему.
Единственное, что не могу понять. Надо, чтобы этих дампов не собиралось там очень уж много.Ну скажем, я делаю бекап регулярно, каждый час. Нафига мне там 24 штуки в сутки чтобы хранились и копились? Надо добавить, чтобы скрипт выполнял проверку на число файлов в директории, и если их там больше скажем 3-х, все старые удалял, оставляя только 3 последних, по времени создания или по именам файлов,в которых как раз продублировано время создания.
если кто подскажет, буду признателен.
ps:
вот щас думал, думал, получается такая штука.
каждый новый дамп будет не больше и не меньше, а только и всегда червертым, если я хочу оставлять скажем три файла, то мне надо удалять всегда один - старейший, ну, или, по логике, имеющий наименьший размер..
Автор: 5trovi4
Дата сообщения: 03.09.2009 12:37
А никто не подскажет, чем отличаются такие вызова второго скрипта из первого?

. 2.sh

2.sh

exec 2.sh

Я раньше думал что знаю, но , как оказалось , на практике как-то не выходит так как я думал.
Автор: vjunk
Дата сообщения: 09.09.2009 19:54

Цитата:
. 2.sh

Будет вызван второй скрипт в контексте текущего интерпретатора, как если-бы его текст был вставлен в это место первого скрипта, второму скрипту доступны все переменные и функции из первого и наоборот.

Цитата:
2.sh

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

Цитата:
exec 2.sh

Будет запущен новый процесс, который заместит собой текущий. Операторы, стоящие после этой строки могут быть выполнены, только если запуск нового процесса не удастся (например, не найден файл второго скрипта).
Автор: Dukat
Дата сообщения: 14.10.2009 08:20
Помогите решить задачку:

Цитата:
Shell-программа подсчитывает количество и выводит список всех файлов (без каталогов) в алфавитном порядке в поддереве, начиная с каталога, имя которого задано параметром Shell-программы. Проверять, что параметр - имя доступного каталога. Форма вывода результата:
каталог <имя каталога> - начальный каталог
<имя файла> - файлы в каталоге
<имя файла>
....
каталог <имя каталога> - подкаталог
<имя файла>
<имя файла>
....
и т.д.

Автор: strden
Дата сообщения: 19.10.2009 10:39
#!/bin/bash

dfm="df -m /xxx | awk '{print $3}' |tail -1" # получить объем свободного места в папке

echo Free = `$dfm` Mb

что то накопировал наудалял

rm /xxx/porno.avi

echo After delete Free = `$dfm` Mb

Подскажите плиз как в параметры правильно заносить составные команды?
Если я буду использовать одинарные апостровы в dfm=`df -m /xxx | awk '{print $3}' |tail -1` то параметру dfm присвоется число свободных Мю в самом начале выполнения скрипта и потом меняться не будет! А мне надо получать в скрипте каждый раз при обращении к $dfm актуальный размер свободного пространства.
Это возможно?
Автор: strden
Дата сообщения: 20.10.2009 09:18
Вот (надеюсь) правильно поставленный вопрос...
Ось Юникс

Как в баш скрипте в переменную занести команду а не значение полученное в результате выполнения этой команды. Дабы потом при каждом вызове этой переменной получать АКТУАЛЬНОе значение (результат выполнения этой команды). Что пытаюсь запомнить в переменную : dfm=$(df -k /tmp | awk '{print $3}' |tail -1)


Надо чтобы при каждом вызове переменной $dfm получать актуальный размер папки ТМП в баш скрипте
Автор: FuzzyLogic
Дата сообщения: 20.10.2009 20:19

Цитата:
Надо чтобы при каждом вызове переменной $dfm получать актуальный размер папки ТМП в баш скрипте

Переменную нельзя вызывать ... в переменных может что-то храниться.

А вызвать содержание того что лежит в переменной точно также как вы делаете, только + eval


Код:
dfm="df -k /tmp | awk '{print \$3}' |tail -1"
eval $dfm
Автор: Tipulatoid
Дата сообщения: 28.10.2009 08:43
Подскажите пожалуйста. Пытаюсь создать массив
Скрипт new

Код:
#!/bin/sh
echo test
a[1]=hjhj
a[2]=jjkjk
echo ${a[1]}
Автор: FuzzyLogic
Дата сообщения: 28.10.2009 18:25
Tipulatoid
Поменяйте

Цитата:
#!/bin/sh

на

Код:
#!/bin/bash
Автор: Tipulatoid
Дата сообщения: 29.10.2009 02:24
FuzzyLogic
Спасибо )
Автор: strden
Дата сообщения: 02.11.2009 13:50
FuzzyLogic
СПАСИБО!
Ваше решение работает!
Нашел еще одно...
Сейчас на вскидку не вспомню.. идея - в переменную занести строку... а потом использовать ее как команду...
ЕЩЕ РАЗ СПАСИБО!
Автор: Timuridze1
Дата сообщения: 13.01.2010 00:39
Проверяет заведомо рабочий сайт, если тот не работает то голосом объявляет о отстутствии подключения к интернет. Но требуеться его доработать, как сделать так что бы после того как он 1 раз объявит что сеть упла он больше не надоедал свомими оповещениями, а после того как инет заработал объявлял о наличии сети и опять успокаивался?
Bcgjkmpetnmcz festival, это голосовой движок под nix, качество отстает от виндовых аналогов но мне хватает.

#!/bin/bash

ip="ya.ru"
count=3
attempt=3
file="./time"

result=$(ping -c ${count} ${ip} | tail -2 | head -1 | awk '{print $4}')
if [ $result -eq 0 ]; then
if [ -f ${file} ]; then
f=$(cat ${file})
if [ ${f} -eq ${attempt} ]; then
rm ${file}
echo "Соединение с интернет отсутствует" | festival --tts
else
att=$(expr ${f} + 1)
fi
else
att=1
fi

if [ ! -z ${att} ]; then
echo ${att} > ${file}
fi
else
if [ -f ${file} ]; then
rm ${file}
fi
fi
Автор: urodliv
Дата сообщения: 28.03.2010 22:21
Граждане.
Со скриптами до сего момента работал на самом примитивном уровне (cat/cut). А тут разбираю чужой стартовый скрипт и натыкаюсь на след. конструкцию.
running () {
.....................
[ -f /var/run/file.pid ] && return 1
.....................
}

Вроде все компоненты кода ясны, а смысл в целом понять не могу. Прошу разъяснить, как работает эта конструкция.
Автор: FuzzyLogic
Дата сообщения: 29.03.2010 03:15
urodliv

Ф-я running если есть файл /var/run/file.pid то возвращает единицу. Т.е. просто проверяет запущен ли какой-то сервис или что-нибудь ещё (хз что такое file.pid )
Часто используемый способ для чего-то что стартует например по расписанию скажем каждые 5 минут чтобы подстраховаться от ситуации в которой программа не успевает сделать всё за те самые пять минут, и чтобы не запускать вторую копию скрипта мы вначале работы создаём пресловутый файл а конце его удаляем (т.е. наличие файла означает что копия скрипта уже работает).
Автор: urodliv
Дата сообщения: 29.03.2010 10:31
Уважаемый FuzzyLogic
Для какой цели у меня эта функция я понимаю. Мне не совсем ясен принцип работы строки
[ -f /var/run/file.pid ] && return 1
Можно ли её расценивать как полный эквивалент следующего выражения:
if [ -f /var/run/file.pid ]; then return 1
И аналогично, в другой функции встречаю похожую конструкцию:
[ -f /var/run/file.pid ] || return 1
Какой существует для неё эквивалент?
Автор: FuzzyLogic
Дата сообщения: 29.03.2010 18:25
urodliv
Извиняюсь, не понял вопроса.


Цитата:

Можно ли её расценивать как полный эквивалент следующего выражения:
if [ -f /var/run/file.pid ]; then return 1

Да, можно

&& указывает что делать если результат [ ] - правда, а || если ложь

т.е. эквивалентом [ -f /var/run/file.pid ] || return 1
будет if [ -f /var/run/file.pid ]; else return 1
Автор: urodliv
Дата сообщения: 12.04.2010 21:44
FuzzyLogic
Я снова к вам с вопросом. Саму проблему я описывал тут.
Вкратце проблема в следующем. В дистрибутиве debian, ubuntu и др. есть два файлика со стандартными функциями: /lib/lsb/init-functions и /etc/lsb-base-logging.sh Непонятка для меня этих файлов в том, что в них обоих присутствуют функции с одинаковыми именами, но несколько разным кодом. Допустим мне необходимо использовать функцию из первого файла. Я его подключаю в свой скрипт. Но в конце первого файла есть такая строка:
[ -e /etc/lsb-base-logging.sh ] && . /etc/lsb-base-logging.sh || true
которая приводит к подключению второго файла. Путём проведения небольшого опыта с различным подключением файлов подтвердил свою мысль о том, что из двух функций с одинаковыми наименованиями будет использоваться та, которая находится ближе к концу файла.
Теперь вопрос. Существует ли какой-либо способ переопределения использования не "последней" подключённой функции, а "первой"? Я понимаю, что можно просто закомментировать последнюю строку в первом файле, но боюсь нарушить "замысел разработчиков". Ведь зачем-то они придумали именно такую структуру.
Автор: CHIEFlab
Дата сообщения: 13.04.2010 11:00
есть два файла, в одном имена пользователей, во втором пароли (строка логина в первом файле совпадает со строкой пароля во втором файле) как автоматизировать такую задачу:
необходимо создать пустые файлы, имя которых соответствует логину, и в них записать проль этого пользователя.
Автор: FuzzyLogic
Дата сообщения: 13.04.2010 17:50
CHIEFlab
ну как-то так:

Код:
#!/bin/bash

FNAMES='names.txt'
FPASSWORDS='passwords.txt'

NAMES=( `cat ${FNAMES}` )
PASSWORDS=( `cat ${FPASSWORDS}` )

NCOUNT=${#NAMES[@]}

for (( i=0; i<${NCOUNT}; i++ )) ; do
echo "Writing ${PASSWORDS[${i}]} to ${NAMES[${i}]}"
echo "${PASSWORDS[${i}]}" > ${NAMES[${i}]}
done
Автор: Maximus777
Дата сообщения: 05.05.2010 13:18
Помогите с написанием скрипта. Надо чтоб на вход подавалось несколько параметров (nfile, spart, npart), затем создавался файл с данными из "nfile", размером равным "spart", содержащий данные вычисляемые по формуле:
fseek(nfile, (размер файла / spart)*npart), SEEK_SET). Где:
nfile - имя файла
spart - размер части
npart - номер части

Т.е. если содержимое файла к примеру myfile="12345678910", то скрипт(myfile, 2, 3) создал бы файл с содержимым "56". Баш вижу практически впервые, поэтому очень сложно написать такое. А вам должно быть раз плюнуть.
Автор: urodliv
Дата сообщения: 05.05.2010 17:15
Решение "в лоб".

#! /bin/bash
#Имя файла скрипта - myscript.sh

B=`expr $2 \* \( $3 - 1 \) + 1`
E=`expr $B + $2 - 1`
cut -c $B-$E $1

Вызов скрипта (при правильно заданных разрешениях): myscript.sh nfile spart npart
Замечание: очевидно, что данное решение применимо только к файлам в содержимом которых нет перевода строки, те есть они содержат только одну строку.
Автор: Maximus777
Дата сообщения: 05.05.2010 18:02
Хм, мне это надо приспособить для разреза фильмов или rar-архивов (внутри которых опять же видео). А хз что там внутри с переводом строки. Ну и файло сами понимаете крупное, т.е. цель отсекать примерно по 1 Гб. Годится ли это решение для таких целей? И спасибо за отклик.
Автор: urodliv
Дата сообщения: 05.05.2010 19:09

Цитата:
Годится ли это решение для таких целей?

Нифига не годится.

Цитата:
Ну и файло сами понимаете крупное, т.е. цель отсекать примерно по 1 Гб.

Крупность файла не самый страшный параметр
Вы бы задачу в целом описали. А то нарезать-то нарежем, но что потом с нарезкой делать будете?
Пока что могу только указать вам на команду split.
[more]Использование: split [КЛЮЧ] [ВХОД [ПРЕФИКС]]
Выводит фиксированного размера части ФАЙЛА в файлы ПРЕФИКСaa,
ПРЕФИКСab, ...; по умолчанию размер части равен 1000 строк, а ПРЕФИКС
равен `x'. Если ФАЙЛ не задан или задан как -, читает стандартный
ввод.

Аргументы, обязательные для длинных ключей, обязательны и для коротких.
-a, --suffix-length=Н использовать суффиксы длины Н (по умолчанию 2)
-b, --bytes=ЧИСЛО записывать в каждый выходной файл заданное ЧИСЛО байт
-C, --line-bytes=ЧИСЛО записывать не более заданного ЧИСЛА байт из строки
-d, --numeric-suffixes использовать числовые, а не алфавитные суффиксы
-l, --lines=ЧИСЛО записывать в каждый выходной файл заданное ЧИСЛО строк
--verbose print a diagnostic just before each
output file is opened
--help показать эту справку и выйти
--version показать информацию о версии и выйти


SIZE may have a multiplier suffix:
b 512, kB 1000, K 1024, MB 1000*1000, M 1024*1024,
GB 1000*1000*1000, G 1024*1024*1024, and so on for T, P, E, Z, Y.[/more]
Автор: Maximus777
Дата сообщения: 06.05.2010 06:08
Спасибо за ответы. Сплит мне не подходит. А задача в принципе простая, есть файл (к примеру 3 Гб), свободное место 1.5 Гб, дык вот надо отрезать сначала 1 Гб с начала файла, слить этот гиг на файлообменник, удалить, затем отрезать следующий гиг, ну и так далее. Решение оказалось гениальным по своей простоте. Спасибо обитателям конференции на jabber.ru. Вот оно:
dd if=file1 of=part2 bs=1048576 count=1024 skip=1024
Эта волшебная строка вырежет из file1 данные, размером 1 Гб, начиная со второго Гб и назовёт это файло part2.
Автор: urodliv
Дата сообщения: 06.05.2010 15:50

Цитата:
Сплит мне не подходит

Ухаха! Ну вы меня повеселили. Сам когда-то такой же ерундой с фильмами страдал, и у меня почему-то split без проблем работал.

Цитата:
dd if=file1 of=part2 bs=1048576 count=1024 skip=1024
Эта волшебная строка вырежет из file1 данные, размером 1 Гб, начиная со второго Гб и назовёт это файло part2.

Ага. А чтобы сделать третью часть будем пересчитывать и править "skip"?
split -d -b 1G file file. - эта команда порежет исходный файл на части размером 1 Гб и то что останется, и назовёт их: file.00, file.01 и т.д.
А дальше пуляйте их куда надо...

P.S. Если мне память не изменяет, то tar`у сам бог велел бить архивы на части.

Страницы: 123456

Предыдущая тема: Сжатие БД формата Access средствами VC++


Форум Ru-Board.club — поднят 15-09-2016 числа. Цель - сохранить наследие старого Ru-Board, истории становления российского интернета. Сделано для людей.