anonymous
написал 18 июля 2004 года в 14:46 (1870 просмотров)
Ведет себя
неопределенно; открыл 1814 темы в форуме, оставил 5575 комментариев на сайте.
Помогите написать прогу, что когда нажимаешь на printscreen на рабочем столе появляется скриншот с номером один, если еще раз нажать то уже номер два и так далее.
вот заготовочка, осталось дописать только операцию с if
Последние комментарии
-
OlegL, 17 декабря 2023 года в 15:00 →
Перекличка
21
-
REDkiy, 8 июня 2023 года в 9:09 →
Как «замокать» файл для юниттеста в Python?
2
-
fhunter, 29 ноября 2022 года в 2:09 →
Проблема с NO_PUBKEY: как получить GPG-ключ и добавить его в базу apt?
6
-
Иванн, 9 апреля 2022 года в 8:31 →
Ассоциация РАСПО провела первое учредительное собрание
1
-
Kiri11.ADV1, 7 марта 2021 года в 12:01 →
Логи catalina.out в TomCat 9 в формате JSON
1
DevOps as a Service from Palark
24/7 SRE & DevOps service to cover all your Kubernetes needs.

#!/bin/sh
import -window root ~/Desktop/$screen.png
Один из вариантов ниже. Усовершенствуйте сами.
Удачи
— sas
Спасибо, ща будем разбираться
Ну вот черновой рабочий вариант
#!/bin/bash
target_dir=~/Desktop
no=$(ls ~/Desktop | sort -t '.' -k 1,1nr | head -n 1 | sed -e ’s/\..*//’)
if [ "$no" = "" ]; then
no=1
else
no=$(($no+1))
fi
import -window root ~/Desktop/$no-screen.png
А скажите что означает вот такая палочка |
и может знаете как в kde отключить появление ksnapshot при нажатии на PrintScreen, и назначить этой кнопочки свою команду
| — это «перенаправление» вывода обной программы на вход другой.
один из наиболее часто используемых взаимодействий программ в unix среде.
подробнее об этом — `man sh` на слове Pipeline
Т.е. это означает, что программы запускаются все вместе, и создаётся «канал» для передачи выходных данных программы слева от | программе справа.
Посмотри в kcontrol в «Региональных и специальных возможностях» раздел «Привязка клавиш». Там же написано, как свою программу в меню записать.
Good Luck,
UT
А вот к примеру даю такую команду rpm -qa *
как мне вывод записать в файл? как с помощью cat создать текстовый файл?
весь kcontrol облазил, даже намека на printscreen не наше
Текстовый файл не имеет стандартного ввода, поэтому пайпом в него вывод программы не загонишь. Но есть два типа редиректа для записи stdout в файл: > и >> Первая переписывает файл с начала, вторая — добывляет к концу
rpm -qa * >> textfile.txt
cat file1.txt > file2.txt
или ты имел в виду, как с помощью echo создать текстовый файл?
Хм, а если ты нажмешь Prnt Scrn, то выскочит ksnapshot? Интересно, где ж она тогда привязана? Ты под KDE работаешь?
Good Luck,
UT
под kde.
когда нажимаешь printscreen то вылезает ksnapshot
Не это?
Regional & access -> Keyboard shortcuts -> Global shortcuts — > Miscellanous -> desktop screenshot
не то
В таком случае, видимо, придётся сменить KDE на более гибкое ;)
Это не означает, что надо так же снести все остальные программы, использующие kde lib. Просто KDE предполагает наличие у пользователя «средних» потребностей. И под них, соответственно, и настроен. Это может и хорошо, но вот.. Свободы настройки куда как меньше.
В общем, меняй kde на какой-нибудь *wm, и задавай вопросики по настройке оного уже в них ;)
Можно сказать мой окончательный вариант:
Если Вы хотите достичь следущего:
1) Спасать скриншоты в какой-то один каталог
2) Получать имя файла для скриншота по правилу: «screen_» + counter + «.png», где counter увеличивается на 1 каждый раз при спасении файла
то Ваш вариант работать правильно к сожалению не будет потому что:
1) «ls -r» — Не будет правильно сортировать файлы.
Например:
# mkdir /tmp/tst
# cd /tmp/tst
# i=1
# while [ $i -lt 21 ]; do
touch screen_$i.png
i=$(($i+1))
done
ls -r
Обратите внимание на порядок файлов screen_1.png screen_10 и т.д.
Можно попробывать использовать «ls -t», но и это будет работать только в случае если системное время не будет меняться и Вы не будете вызывать скрипт в пределах 1 секунды. :)
Самое надежное в этом случае использовать sort и правило для имени:
«screen_» + counter + «_.png»
'_’ — sort может использовать как ограничители полей
2) Вам тут grep после ls не нужен. Зачем лишний процесс стартовать?
3) Вместо 2-х sed нужен 1
Т.е. предлагаю следующий вариант (не тестирован):
Успехов
— sas
PS Теоретически у предложенного вырианта тоже могут быть проблемы, если более чем один скрипт запущен в системе одновременно. Лечение на уровне скрипта — наверное утилита lockfile (man lockfile). Она входит в sendmail, если не ошибаюсь.
1) скриншоты создаются в каталоге и которого запускается скрипт
2) grep нужен для того чтобы ls не выводил сообщение об отстутствии *.png файлов (в каталоге и которого запускается скрипт).
3) ls -t у меня работать будет, поскольку время работы import этого скрипта у меня порядка 3-х секунд.
Итоговый вариант:
Нам лишнего не надо :)
#!/bin/bash file_prefix="screen_" file_ext="png" no=$(ls -t ${file_prefix}*.${file_ext} 2>/dev/null | head -n 1 | sed -e 's/[^0-9]//g') if [ -z $no ]; then no=1 else no=$(($no+1)) fi target="${file_prefix}${no}.${file_ext}" echo "Write file ${target}" import -window root ${target}А пользователю ведь никто не запретит по мышке или по Enter быстро нажимать, поэтому лучше sort. И кстати зачем же писать скрипты, которые на быстродействие конкретной машины и видео режим завязаны? Сами же и навернетесь когда нибудь или Ваши друзья/клиенты. Настоятельно рекомендую хотя бы lockfile использовать.
Удачи
— sas
-- Используется lockfile и «ls -r»
-- Не удалось уйти от двух sed’ов
#!/bin/bash lock_prefix="/tmp/screen.lock" lock_suffix=`eval date +%s` lockfile="${lock_prefix}.${lock_suffix}" lockfile $lockfile file_prefix="screen_" file_ext="png" no=$(ls -r ${file_prefix}*.${file_ext} 2>/dev/null | head -n 1 | sed -e 's/[^0-9]//g' | sed -e 's/^0*//') if [ -z $no ]; then no="1" else no=$(($no+1)) fi if [ $no -lt "100" ]; then no="0${no}" fi if [ $no -lt "10" ]; then no="0${no}" fi target="${file_prefix}${no}.${file_ext}" echo "Write file ${target}" import -window root ${target} rm -f $lockfile1. И самое важное lockfile то у Вас так работать не будет, т.к. для каждого процесса создается с «почти» уникальным именем. Вы хотели заблокировать запуск более одного процесса в течении 1-ой секунды, но это не пройдет в некоторых случаях.
Правильное решение:
* Имя файла должно быть одинаково для всех процессов
* Если скрипт будет прерван по каким либо причинам (например Ctrl+C), то Ваш лок не будет удален. Решение проблемы — использование trap
2. У Вас существует ограничение на число уникальных файлов скриншотов в одном директории (max == 999). Это ограничение искусственное и в принципе никому не нужное, хотя число файлов и велико. Существуют как мне кажется следующие решения (в порядке от наименее предпочтительных к более):
* Как минимум надо пользователю сказать, что число файлов превысило максимальное и скрипт работать не будет (+код выхода != 0)
* Сказать пользователю, что после 999 файла будем перезаписывать начиная с 1-го (+код выхода != 0), что тоже не очень удобно, т.к. пользователю в этом случае сложней найти нужный скриншот
* Как я уже говорил 3 раза — используйте sort и этой проблемы не будет вообще
3) Второй sed не нужен:
# i=00132
# i=$(($i+1))
будет работать и так
Если Вы все-таки хотите использовать 999 ограничение или 9999 :), то используйте команду printf
printf '%04d\n' $i
4) Ваше lock_suffix=`eval date +%s` — то же самое, что и lock_suffix=`date +%s` или, более наглядно lock_suffix=$(date +%s)
Успехов
— sas
-- Использую trap
-- Использую printf
-- Предупреждаю пользователя
-- Второй sed нужен. Без него (у меня) при $no=0008, $no на единицу увеличиваться не хочет.
#!/bin/bash lockfile="/tmp/screen.lock" trap "rm -f ${lockfile}" INT lockfile ${lockfile} file_prefix="screen_" file_ext="png" no=$(ls -r ${file_prefix}*.${file_ext} 2>/dev/null | head -n 1 | sed -e 's/[^0-9]//g' | sed -e 's/^0*//') if [ -z $no ]; then no="1" else if [ $no = "999" ]; then echo "Delete screenshot!!!" rm -f ${lockfile} exit -1 fi no=$(($no+1)) fi target=`printf 'screen_%04d.png\n' $no` echo "Write file ${target}" import -window root ${target} rm -f ${lockfile}Good :) Much better. Sorry for 0+. My fault. :(
Warning: was not tested.
#!/bin/bash # --- Error codes. ERR_LOCK=-1 ERR_MAX_NO=-2 # --- maximum number of the screenshots MAX_NO=9999 # --- lockfile related TIMEOUT=10 RETRIES=1 lockfile="/tmp/screen.lock" # --- target file related file_prefix="screen_" file_ext="png" # --- Ok, starting trap "rm -f ${lockfile}" INT lockfile -${TIMEOUT} -r ${RETRIES} ${lockfile} 2>/dev/null if [ $? -ne 0 ]; then echo "Cannot lock!" >&2 exit ERR_LOCK fi # --- 1 sed no=$(ls -r ${file_prefix}*.${file_ext} 2>/dev/null | head -n 1 | sed -e 's/[^0-9]//g; s/^0*//') if [ -z $no ]; then no="1" else # --- If printf '%04d, then not 999 but 9999 if [ $no -eq ${MAX_NO} ]; then echo "Delete screenshot!!!" >&2 rm -f ${lockfile} exit ERR_MAX_NO fi no=$(($no+1)) fi target=$(printf 'screen_%04d.png\n' $no) # # --- to make script a little bit more responsive we should not wait until import is # finished. Just "reserve" our file and remove the lock, so next process can # start faster # touch $target rm -f ${lockfile} echo "Write file ${target}" import -window root ${target}Good luck
— sas
no=$(ls -r ${file_prefix}*.${file_ext} 2>/dev/null | head -n 1 | sed -e ’s/[^0-9]//g' | sed -e ’s/^0*//’)
заменить на
no=$(/bin/ls -r ${file_prefix}[0-9]{1,4}.${file_ext} 2>/dev/null | head -n 1 | sed -r ’s/^[^1-9]*([0-9]+)[^0-9]*$/\1/g’)
/bin/ls — во избежание alias
regexp у sed — ну, и так понятно
Классное дополнение. Спасибо. Только последнее g в sed не нужно, т.к. используются ^ и $
Успехов
— sas
Тогда уж и head уберите:
no=$(/bin/ls -r ${file_prefix}[0-9]{1,4}.${file_ext} 2>/dev/null | sed -r '1s/^[^1-9]*([0-9]+)[^0-9]*$/\1/g')И получим, скажем, строку «990 screenshot_989.png screenshot_988.png …»
Кстати, немного я ошибся.
Нет в shell возможности указать сколько символов смотреть, поэтому:
no=$(/bin/ls -r ${file_prefix}*.${file_ext} 2>/dev/null | head -n 1 | sed -r 's/^[^1-9]*([0-9]+)[^0-9]*$/\1/')head и sed тоже желательно бы оградить от переопределения их в alias…
как-нибудь так:
PATH=/bin:/usr/bin $LS=`which ls` || exit -2 # это значит, что не нашли $HEAD=`which head` || exit -2 $SED=`which sed` || exit -2 no=$($LS -r ${file_prefix}*.${file_ext} 2>/dev/null | $HEAD -n 1 | $SED -r 's/^[^1-9]*([0-9]+)[^0-9]*$/\1/')Ну опечатка, конечно. -n забыл. Или q в команде. По вкусу, в общем.
Ну я думаю, что все таки лучше и правда ограничить ls в этом случае:
ls -r $file_prefix[0-9][0-9][0-9][0-9].$file_ext (т.к. выбрана схема в которой мы заранее знаем сколько цифр в числе.Недостаток этого ограничения обсуждать не предлагаю :) )
Это важно в случае, если в директории есть например файл с именем screen_creen.png, то наш номер всегда будет равен 1
Или можно вернуться к предложенному Master-ом grep после ls
Кроме того, все таки, по размышлении, я бы использовал sed -e ’s/[^0-9]//g; s/^0*//' без расширенных регулярных варажений из-за портабельности, т.к. не все sed их поддерживают.
Это только мнение :)
Удачи
— sas
поэкспериментировал я тут немного… ;)
получилось вот такое ;)
правда — на перле, что малость удобнее и проще.
ИБО: Атомарный лок в shell — сделать сложно.
#!/usr/bin/perl use Fcntl qw(:DEFAULT :flock); $lockfile="/var/lock/screenshot.lock"; $ss_folder="."; $ss_prefix="screenshot_"; $ss_suffix=".png"; $ss_digits=4; $ss_timeout=0.1; $ss_retries=20; $pattern="${ss_prefix}[0-9]{$ss_digits}${ss_suffix}"; $npattern="${ss_folder}/${ss_prefix}%0${ss_digits}d${ss_suffix}"; if(opendir(DIR,"${ss_folder}")) { waitforlock($lockfile); $file=(reverse sort grep(/$pattern/, readdir DIR))[0]; if($file=~/([0-9]+)/) { $no=1+$1; } else { $no=0; } $newfile=sprintf($npattern,$no); touchfile($newfile); system("import -window root ${newfile} &"); } sub waitforlock { my $handle=shift; my $count=0; until(sysopen(FH, $lockfile, O_WRONLY|O_CREAT) && flock(FH, LOCK_EX|LOCK_NB)) { sleep $ss_timeout; if(++$count > $ss_retries) { print "Sorry, can't create screenshots right now\n"; exit; } } } sub touchfile { my $handle=shift; open(FILE,">$handle"); close(FILE); }Последний перл скрипт от Гения мне сказал sorry.
Последний sh скрипт sas работат нормально, но есть одна проблема скрипт сделан для запуска его из консоли, но в консоли мне не нужно делать скриншоты. Поставал я на кнопочку printscreen запуск этого скрипта, и если кнопку удерживать, то открывается много printscreen и при этом они работают секунд по 20 (под курсором появляются часики и в таскбаре висят — некрасиво).
Как сделать чтобы при зажатии printscreen запускался только один скрипт, а следущий раз он запускался только когда я повторно зажму кнопку и пусть он как только сделал скрин завершал работу, не ждал бы чего, было бы вообще здорово еслибы он в фоне работал, просто на рабочем столе появлялся бы скриншот после нажатия кнопки, без каких либо сообщений о том что работал скрипт.
1) Перманентно «Sorry…» мой скрипт сказать мог только в том случае, если в /var/lock данный пользователь не может писать. Что, в общем-то, странно, так как /var/lock, /var/run имеют такие же права (по крайней мере в debian), как и /tmp.
Поэтому, если возникает такая проблема — надо просто поменять местоположение этого файла. Да на /tmp/screenshot.lock, к примеру. Или где-то в домашнике.
2) Так же необходимо настроить остальные переменные (к примеру, создать папку ~/screenshots и указать полный путь до неё в переменной $ss_folder. Так же надо настроить и остальное по желанию.
3) Что касается не ожидания, а выхода из скрипта сразу. Участок кода
заменить на простое
Вот на Python`e
printscrn.py ——————————————--
#! /usr/bin/env python
import os,sys,pwd
try:
quality = sys.argv[1]
if 0 < int(quality) <= 100:
pass
else:
print «\033[1;31mError:\033[m Quality range > 0 or >= 100"
except:
quality = 90
printdir = "%s/Screen" % pwd.getpwnam(os.environ.get("USER"))[5]
if os.path.exists(printdir):
pass
else:
os.mkdir(printdir)
try:
filelst = os.listdir(printdir)
num = int(len(filelst))
file = «Screen%02d.png» % num
if os.path.exists(«%s/%s» % (printdir,file)):
num = num + 1
file = «Screen%02d.png» % num
except:
file = «Screen%02d.png» % 0
os.system(«import -window root -quality %s %s/%s» % (quality,printdir,file) )
print «ScreenShot copying to [ %s/%s ]» % (printdir,file)
——————————--
[root@localhost Desktop]# python2.3 printscrn.py
File «printscrn.py», line 8
pass
^
IndentationError: expected an indented block
НЕ работает
Там все рыботает !, просто надо правильно поставить отступы !