2015-02-09 5 views
0

Я хотел бы проверить, был ли файл создан и внесен в определенный каталог, который был подключен через SaMBa к машине Linux. Основываясь на дате, он должен проверить, есть ли файл с датой в имени. Сначала я создаю то, что должен искать «ls», тогда я делаю оператор if-else. Я что-то упустил, или мой код не так? Использование/bin/env bash. Вот мой сценарий:проверить, существует ли файл bash, не работает

#!/usr/bin/env bash 
YESTERDAY=`date +%Y-%m-%d -d "yesterday"` 
#YESTERDAY="test" 
LOCATION="/some/directory/some/other/directory" 
FILENAME="$LOCATION/*MEMB*$YESTERDAY*" 

echo "Filename is $FILENAME" 
if [ -e "$FILENAME" ] 
then 
    echo "Found \"$FILENAME\" files from yesterday. WILL NOT SEND EMAIL." 
else 
    echo "FILE FROM YESTERDAY \"$FILENAME\" NOT FOUND" 
fi 

Он никогда не попадет в «истинное» заявлении на всех, даже если есть файлы в директории со вчерашнего дня, а «остальное» выполняет все время. Если я изменил значение «ВЧЕРА» на «2015-02-09» (сегодня) или любое другое значение, которое истинно, оно также не попадет в истинное утверждение.

Я пробую литеральную директорию без переменной в -e, и она работает. Об одном единственном, когда я могу заставить конструкцию if работать, если я устанавливаю «имя файла» в файл в том же каталоге сценария. Не игнорирует ли слэш в тесте -e? Пожалуйста, предложите альтернативные способы.

В случае, если есть альтернатива, я знаю следующие сценарии: C++, Perl, начинающий-промежуточный сценарий bash, PHP и JavaScript. Благодаря!

+0

FYI, имена всех шапок зарезервированы для переменных среды и встроенных оболочек; используя их для переменных, локальных для вашего сценария, рискует столкновениями пространства имен. –

+0

Кроме того, BashFAQ # 4 находится на месте по этому вопросу: http://mywiki.wooledge.org/BashFAQ/004 –

ответ

3
FILENAME="$LOCATION/*MEMB*$YESTERDAY*" 
[ -e "$FILENAME" ] 

... ищет имя файла с буквальным * символов в имени, а не для соответствуют ли какие-либо файлы шаблона заданной.

Решение, которое может выглядеть очевидным для некоторых людей, используя [ -e $FILENAME ] без кавычек, не работает, либо - так как он вычисляет [ -e ] если есть нулевые результаты и nullglob устанавливается (это эквивалентно [ -n -e ], и оценивает как истина!) и недопустимой командной строке test, если более одного файла соответствует glob, что приводит к ошибке и ложному результату.

Вместо загрузки списка соответствующих файлов в массив, и проверить его длину (и, если вы не запускали shopt -s nullglob, а также проверить, что первый элемент массива существует):

# Important: Double-quote the parameter expansions, but NOT the globs! 
filenames=("$LOCATION"/*MEMB*"$YESTERDAY"*) 
if ((${#filenames[@]})) && [[ -e ${filenames[0]} ]]; then 
    echo "At least one file matches the name" >&2 
else 
    echo "No files exist" >&2 
fi 

Дополнительная сложность здесь заключается в том, что по умолчанию выражение glob без совпадений расширяется до самого себя, поэтому вы можете получить одно имя, возвращенное - нерасширенное выражение glob. Вы можете сказать, скорлупу не делать с опцией nullglob:

shopt -s nullglob 
filenames=("$LOCATION"/*MEMB*"$YESTERDAY"*) 
if ((${#filenames[@]})); then 
    echo "At least one file matches the name" >&2 
else 
    echo "No files exist" >&2 
fi 

Кстати, если ваша оболочка POSIX Sh вместо баш, то вы можете избежать необходимости использовать массивы. Вы можете сделать это, определив функцию (чтобы иметь свой собственный список аргументов, так что вы не переписывая глобальный), а затем с помощью вектора аргументов, чтобы держать ваши совпадающие имена файлов:

check_for_filenames() { 
    if [ "$#" -gt 0 ] && [ -e "$1" ]; then 
    echo "At least one file matches the name" >&2 
    return 0 
    else 
    echo "No files match" >&2 
    return 1 
    fi 
} 
check_for_filenames "$LOCATION"/*MEMB*"$YESTERDAY"* 
+0

Является '' '' опечаткой в ​​'filenames = (" $ LOCATION "/ *" $ MEMB "* «$ ВЧЕРА» *) '? – user3439894

+0

@ user3439894, Да - на моем первом проходе я читал это как расширяющуюся переменную. Я попытался вернуться и исправить это, но, видимо, пропустил экземпляр. –

+0

@CharlesDuffy спасибо, я думаю, что попробую. Моя альтернатива - Perl. –

0

После ваших предложений, Я закончил вывод результатов команды ls в переменную, а затем содержимое этой переменной в файл. Читая каждую строку в файле, видя, соответствует ли она «вчерашнему» шаблону, затем включив флаг, если это так, чтобы проверить и отправить электронную почту. Я закончил тем, что это:

# LET'S SAVE TODAY'S DATE FROM YESTERDAY 
yesterday=`date +%Y-%m-%d -d "yesterday"` 
foundMEMB="no" 

location="/some/directory/location" 
echo "RESULTS in /some/directory/location" > empty.log 
filename=$location/*$yesterday* 
results=`ls $location/MEMB$yesterday*` 
echo "$results" >> empty.log 
for i in $(cat empty.log) ; do 
    #echo item: $i "is good" 
    if [[ "$i" =~ "$yesterday" ]]; then 
      echo "$i matches $yesterday" 
      foundMEMB="yes" 
    fi 
done 
if [[ "$foundMEMB" == "no" ]]; then 
    mail -s "Found no MEMB file from date $yesterday." email_atsymbol_domain < empty.log 
fi 
echo "END" 
exit $? 

Так что работал хорошо, потому что теперь я могу видеть то, что было сделано, если я когда-либо смотреть на empty.log и раньше, я не мог. Я все еще учился, поэтому мне было так комфортно. Спасибо за помощь!

Смежные вопросы