Лично я считаю, что вложенный оператор if
здесь вполне уместен, хотя я бы использовал слегка модернизированный синтаксис:
if [ "$a" = "y" ] || [ "$a" = "Y" ]; then
if printf '%s' "$b" | grep -qE 'SOME_REGEX'; then
# both conditions met: do stuff
fi
fi
(обратите внимание, что ==
являетсяbash
-измом)
Их объединение (делает его менее читабельным ИМХО):
if [ "$a" = "y" ] || [ "$a" = "Y" ] && printf '%s' "$b" | grep -qE 'SOME_REGEX'; then
# both conditions met: do stuff
fi
Для базовых регулярных выражений вы можете использоватьexpr
(см. комментарий Стефана Шазела ниже, хотя):
if [ "$a" = "y" ] || [ "$a" = "Y" ] && expr "$b" : 'SOME_REGEX' >/dev/null; then
# both conditions met: do stuff
fi
Оболочка /bin/sh
обычно не имеет [[... =~... ]]
расширенного сопоставления регулярных выражений.
Что касается вашего примечания в конце :Регулярные выражения предназначены для сопоставления отдельных строк текста . Если вы обрабатываете имена файлов как текст, вы автоматически исключаете любое имя файла, которое не является одной строкой текста, например, имена файлов, содержащие символы новой строки. Если вам нужно применить сопоставление регулярных выражений к именам файлов, делайте это осторожно с именами, хранящимися в массиве($@
в /bin/sh
), или используйте реализацию find
, которая поддерживает предикат -regex
.
Шаблоны подстановки имен файлов предназначены для сопоставления имен файлов.
Я изменил то, что вы предоставили, чтобы добавить цикл for, в котором вы можете указать различные префиксы журнала. Это предполагает, что вы вызываете этот скрипт каждые 15 минут из планировщика заданий, такого как cron или autosys, если нет, то его можно обернуть в цикл while true с 15-минутным спящим режимом.
TIMESTAMP=`date "+%Y.%m.%d-%H.%M"`
LOGS="AppA AppB"
# to pull log prefixes from a file replace with the next line
#LOGS="$(cat prefixes.txt)"
LOGSUFFIX=".log.4"
APPLOGS_DIR="/logs"
BACKUP_DIR="/backupDIR"
for LOG in ${LOGS}
do
if [ -f "${APPLOGS_DIR}/${LOG}${LOGSUFFIX}" ]
then
mv "${APPLOGS_DIR}/${LOG}${LOGSUFFIX}" "${BACKUP_DIR}/${LOG}_${TIMESTAMP}"
gzip "${BACKUP_DIR}/${LOG}_${TIMESTAMP}"
else
echo "No ${LOG}${LOGSUFFIX} file to be backed up"
fi
done
вы можете использовать цикл for
и использовать манипуляции со строками для создания имени выходного файла ${var%.*}
на основе имени входного файла
TIMESTAMP=$(date "+%Y.%m.%d-%H.%M")
APPLOGS_DIR="./logs"
BACKUP_DIR="./backupDIR"
# canonicalize relative paths
APPLOGS_DIR=$(realpath "$APPLOGS_DIR")
BACKUP_DIR=$(realpath "$BACKUP_DIR")
# delete this line - just for demo
echo "AppA.log.4\nAppB.log.4" >>./index.txt
# read file names from list
LOGS=$(sort./index.txt | uniq) || exit 127
cd "$APPLOGS_DIR" || exit 127
for log in $LOGS
do
if [ -f "$log" ]
then
mv -f $log "$BACKUP_DIR"
cd "$BACKUP_DIR" || exit 127
mv $log ${log%.*}_${TIMESTAMP}
gzip ${log%.*}_${TIMESTAMP}
cd "$APPLOGS_DIR"
else
echo "No log file to be backed up"
fi
done
Однако просто архивировать и удалить файл можно и безcd
while IFS='' read -r log || [ "$log" ]
do
[ -f "$APPLOGS_DIR/$log" ] && \
gzip -nc "$APPLOGS_DIR/$log" > "$BACKUP_DIR/${log%.*}_${TIMESTAMP}.${log##*.}.gz" && \
rm "$APPLOGS_DIR/$log" || \
echo "No '$log' file to be backed up"
done <<< $(sort./index.txt | uniq)
или как один -вкладыш (, когда имена выходных файлов не имеют значения и имена файлов не содержат пробелов )используйте флаг -S
для суффикса и обработайте index.txt прямо из gzip
без петли
cd "$APPLOGS_DIR" && \
gzip -S.${TIMESTAMP}.gz $(cat $OLDPWD/index.txt) && \
mv -f *.${TIMESTAMP}.gz "$BACKUP_DIR"