Скрипт для отправки всех соответствующих файлов в каталог

Попытка настроить скрипт bash для автоматизации отправки файлов данных. Желаемый конечный результат – проверять указанный каталог раз в неделю, составлять список всех файлов Excel, измененных за последние 2 дня, и отправлять их по электронной почте в назначенный список получателей.

У меня настроен и работает sendmail (с использованием реле Gmail). У меня есть настройка и работа. В общем, команды, которые я пытаюсь отправить, работают, если отправлять их напрямую из CLI (почта отправляется и принимается с вложениями), но я получаю повторяющиеся сбои при попытке вызвать их из скрипта. Все, кажется, связано с тем, что имена каталогов и файлов содержат пробелы. Я не могу изменить это – у меня нет контроля над наименованием файлов, но похоже, что это ключевой момент в моем скрипте.

Две основные проблемы:

  1. Если я попытаюсь отправить все файлы за один раз, сообщается, что прикрепленные файлы не могут быть прикреплены:
Can't stat "/path\ to/file1.xls /path\ to/file2.xls": No such file or directory 

Символ новой строки передается как часть переменной $ FILES.

  1. Если я попытаюсь прокрутить каталог для отправки файлов по одному (мой желаемый результат, так как некоторые файлы довольно большие), скрипт интерпретирует пробелы как разделители, экранированные или нет – так /path/to/the\ files/file\ 1.xls рассматривается как 3 значения ( /path/to/the\ , files/file\ , 1.xls ).

У меня была первая половина скрипта, работающего (посылая все файлы сразу), но удалось сломать его, пытаясь добавить цикл. Конечно, я не сохранил более раннюю рабочую версию. Пробовал использовать set ifs=$'\n' для того, чтобы цикл получил правильные разделители, но когда у меня есть это, mutt сообщает мне, что полный путь к файлу не является файлом или что не было назначенного адресата. Это немного смущает.

Автор сценария:

 #!/bin/bash # This file should send an email to specified recipients with data files for the week attached. # Set reply-to address for Mutt export REPLYTO="my_email@domain.com" # Replace with space separated email address of all recipients EMAILS="recipient1@domain.com recipient2@domain.com" # Get today's date for subject # Date is in YYYY-MM-DD format TODAY=$(date +%F) # Set the message body MBODY="Sending this week's data files.\n" # Set the starting directory # Don't bother escaping it, this is fixed in FILES variable below DIR="/home/user/path to files" # Get the list of files to send FILES=$(find "$DIR" -type f -mtime -2 | sed 's/ /\\ /g' | grep ".xls") # Check to see if we found any files or not if [ -z "$FILES" ]; then MBODY="No matching files added or modified within last 2 days. No files sent.\n" echo "$MBODY" | mutt -s "Data files for $TODAY" $EMAILS fi # Send all files in a single email echo $MBODY | mutt -s "Data files for $TODAY" -a "$FILES" -- $EMAILS 

Для отправки файлов по отдельности я попробовал следующее вместо двух последних строк:

 # Cycle through FILES array and send each file individually for datafile in ${FILES[*]} do set IFS=$'\n\t' echo $MBODY | mutt -s \"Data files for $TODAY\" -a $datafile -- $EMAILS unset $IFS done 

Любая помощь? Некоторое время я застрял на этом. Я не женат на использовании mutt или даже bash, если это проще сделать на другом языке.

3 Solutions collect form web for “Скрипт для отправки всех соответствующих файлов в каталог”

 set "/home/user/path to files/"*.xls for f do [ "$f" -nt "$two_day_old_file" ] && set "$@" "$f" ; shift ; done touch "$two_day_old_file" echo $MBODY | mutt -s "Data files for $TODAY" -a "$@" -- $EMAILS 

Чтобы отправить их по почте, поменяйте echo строку на:

 for mailf do echo "$MBODY" | mutt -s "Data files for $TODAY" -a "$mailf" -- $EMAILS done 

Вероятно, будет работать, но ваша настоящая проблема кроется здесь:

 ... set IFS=... ... 

Это вообще не влияет на значение внутреннего разделителя полей, а скорее присваивает значение IFS=... первому позиционному параметру или $1 . $IFS остается ценным в том, что было до того, как вы set $1 . Вам просто нужно сделать:

 IFS=' ' 

Или…

 IFS=${IFS# } 

… если $IFS установлено на значение по умолчанию, которое должно быть, если это исполняемый скрипт, и вы не изменили $IFS нигде в скрипте.

Проблема в том, что $FILE – это не массив, но вы обращаетесь к нему так, как будто это

 for datafile in ${FILES[*]} 

Он просто возвращает гигантскую строку, следовательно, все файлы сразу.

Чтобы обойти это, добавьте новую строку для каждого файла в $FILE затем в цикле используйте echo -e чтобы возвращать каждую строку индивидуально

 # Get the list of files to send FILES=$(find "$DIR" -type f -mtime -2 | sed 's/ /\\ /g' | grep ".xls" | sed '/.xls$/ a\\\n') 

тогда

 for datafile in $(echo -e $FILES) do echo $MBODY | mutt -s \"Data files for $TODAY\" -a "$datafile" -- $EMAILS done 

Кроме того, добавление двойных кавычек в файл $datafile должно устранять проблему с пробелами в именах файлов

Похоже, вычислить рабочий метод. Избегайте $IFS и не пытайтесь обрабатывать весь список каталогов в виде строки или массива – работайте над каждой записью, когда она найдена. Замените последний цикл следующим:

 find "$DIR" -type f -mtime -2 -name '*.xls*' -exec sh -c ' for file do # Check to see if we found any files or not if [ -z "$file" ]; then echo "$NOBODY" | mutt -s "Data files for $TODAY" $EMAILS # If we found files, then email them else echo "$MBODY" | mutt -s "Data files for $TODAY" -a "$file" -- $EMAILS fi done ' sh {} + 

где $NOBODY – это другой орган сообщения, в котором не указаны соответствующие файлы. Использование "*.xlsx*" для обеспечения соответствия файлов .xls и .xlsx. Это сработало, но указанные выше переменные не попадали в цикл. Я предварял каждую команду export , после чего выше это делает трюк. (Если есть более элегантный способ получить переменные в цикле, я не нашел его. 99% обсуждений по циклам и переменным относятся к тому, как вернуть их обратно из цикла, а не INTO).

  • Безопасно ли удалить файл сценария из этого скрипта?
  • Как переместить кусочки данных между двумя словами, если у данных есть процентный символ в начале?
  • «Login -qf», поскольку root приводит к ошибке «Ошибка входа в систему»
  • Как использовать awk для печати только строк, содержащих 5 столбцов
  • Поверните изображение, если ширина больше значения (то есть в пикселях)
  • Есть ли способ, с помощью которого я могу рекурсивно рекурсивно перебирать все файлы в текущем каталоге, чтобы найти шаблон, а затем распечатать его в порядке от максимума до минимума?
  • Есть ли способ увидеть, какой процесс вызвал сценарий оболочки?
  • Проверить файл .bash_profile перед загрузкой?
  • Когда `ls -s` печатает" 0 "
  • Почему параметр $ 0 дает мне только базовое имя вместо полного пути после преобразования x-shellscript в x-исполняемый?
  • Сортировка файлов с определенным расширением с измененным временем и сохранение их в массив
  • Linux и Unix - лучшая ОС в мире.