cd /path/to/abc; cnt=0; for i in *.*; do mv "$i" "${PWD##*/}_$((++cnt)).${i##*.}"; done
cd
войти в этот каталог *.*
используется только для выбора файлов с суффиксом mv
на echo
, чтобы посмотреть, как будет выглядеть результат, прежде чем возиться Редактировать:
Если вы хотите сделать это для нескольких каталогов, сбросьте счетчик в каждом каталоге.
Один вкладыш:
for i in */*.*; do [ "$dn" != "${i%/*}" ] && cnt=0; dn="${i%/*}"; mv "$i" "${dn}/${dn}_$((++cnt)).${i##*.}"; done
Красиво напечатано:
for i in */*.*; do
# reset counter if different directory or dn is unset
[ "$dn" != "${i%/*}" ] && cnt=0
# set directory name
dn="${i%/*}"
# move file
mv "$i" "${dn}/${dn}_$((++cnt)).${i##*.}"
done
Ваша попытка с sleep
не сработает, поскольку вызов sleep
и последующая проверка $flag_cancel
происходят в фоновом задании. Любое изменение переменной flag_cancel
в основной части кода не повлияет на значение переменной в фоновой подоболочке, и код безоговорочно приостановит работу системы через 10 секунд.
Вместо этого вы можете использовать тот факт, что и read
, и select
истекают через $TMOUT
секунд в bash
.
Вот вариация на тему вашего первого фрагмента кода:
suspend_maybe ()
{
local PS3='Please confirm/cancel system suspension: '
local TMOUT=10
local do_suspend=true
select confirmation in confirm cancel; do
case $REPLY in
1)
# default case
break ;;
2)
do_suspend=false
break ;;
*)
echo 'Sorry, try again' >&2
esac
done
if "$do_suspend"; then
echo 'Suspending...'
systemctl suspend
else
echo 'Will not suspend'
fi
}
Внесены изменения:
suspend_maybe
, поскольку в bash
уже есть встроенная -в suspend
утилита. select
использует PS3
в качестве подсказки. select
истекает через $TMOUT
секунд.case
. Таким образом, нам не нужно вводить все строки дважды. Значение $REPLY
будет любым, что введет пользователь. select
нам нужен только для того, чтобы сообщить нам, хочет ли пользователь отменить приостановку работы системы. Мы рассматриваем приостановку как действие по умолчанию. select
, мы приостанавливаем работу системы, если только пользователь не решит отменить это действие. То же самое, но с входным контуром, использующим read
в качестве отвода -вместоselect
:
suspend_maybe ()
{
local PS3='Confirm system suspension [y]/n: '
local TMOUT=10
local do_suspend=true
while true; do
if ! read -p "$PS3"; then
# timeout
break
fi
case $REPLY in
[yY]*)
# default case
break ;;
[nN]*)
do_suspend=false
break ;;
*)
echo 'Sorry, try again' >&2
esac
done
if "$do_suspend"; then
echo 'Suspending...'
systemctl suspend
else
echo 'Will not suspend'
fi
}
Здесь пользователь может ввести любую строку, начинающуюся с n
или N
, чтобы отменить приостановку. Истечение времени ожидания read
, ввод слова, начинающегося с y
или Y
, или нажатие Ctrl+D приведет к приостановке работы системы.
В приведенном выше цикле легче поймать случай тайм-аута, если вы хотите сделать что-то особенное, когда приостановка происходит из-за того, что пользователь не отвечает на приглашение. break
в оператореif
-будет запускаться всякий раз, когда вызов read
терпит неудачу, что происходит по истечении времени ожидания (или при закрытии входного потока ).
Вы также можете сделать это с помощью at
. Преимущество :Если вам нужно освоить новый инструмент, изучите самый универсальный. at
назначает команды в произвольное время в будущем. Запланированные задания можно удалить из очереди с помощью atrm
.
В вашем случае:
function suspend()
{ #
JOBNO=$(echo "systemctl suspend" | at now + 0.2 seconds 2>&1 > /dev/null | awk '{print $2}')
echo "Please confirm/cancel system suspension:"
select confirmation in "confirm" "cancel"; do
case ${confirmation} in
confirm )
echo "System suspending..."
systemctl suspend
break;;
cancel )
echo "Canceled suspension."
break;;
esac
atrm $JOBNO
done
}
Можно использовать параметр t
команды read
.
Например;
read -t 5 -p "Input within 5 seconds:" data
if [[ $data ]]
then
echo " Your input is $data"
else
echo " You didn't any input"
fi
Запустить скрипт;
Если ничего не вводить в течение 5 секунд;
#~ bash scr.sh
Input within 5 seconds: You didn't any input
Если ввести данные через 5 секунд;
#~ bash scr.sh
Input within 5 seconds:new data
Your input is new data
В общем, у вас есть альтернатива timeout
из GNU coreutils . Здесь не лучший выбор,потому что мы устанавливаем тайм-аут для встроенной команды, а внешняя утилита может сделать это, только создав целую оболочку:
if ! timeout 10 bash -c '
select conf in yes no
do
case $conf in
(yes) exit 1;;
(no) exit 0;;
esac
done'
then
echo 'Suspending'
fi
Вероятно, будет интереснее, если вы собираетесь запросить ввод данных от пользователя через какой-то внешний инструмент, возможно, графический (хотя некоторые из них реализуют свой собственный механизм тайм-аута ).
Обратите внимание, что для timeout
требуется опция --foreground
, если она не вызывается напрямую из приглашения оболочки (, например, если вы вызываете ее в подоболочке:( timeout... )
)и ей нужно читать из терминала.