Выйдите из сценария оболочки, если файл не существует

#shell #file #ksh

Вопрос:

У меня есть задание .sql, которое создает файлы в зависимости от определенных критериев, оно записывает их с префиксом TEMP_, так как у нас есть адаптер, который собирает файлы, и мы не хотим, чтобы они были собраны до завершения записи. Мне нужно создать почтовое задание, которое переименовывает эти файлы, я настроил его вместе с рядом других заданий, но все они создают файлы при каждом запуске. Это задание создает файлы только иногда, когда оно выполняется, в зависимости от данных в системе. Мне нужно проверить, существует ли файл, а затем выйти, если файл не существует.

Я нашел несколько примеров, но все они, похоже, терпят неудачу, вот где я дошел до того, что, как я думал, проверял, нет ли файла, если нет файла, затем выйдите, но это не удается, и отображается: «синтаксическая ошибка в строке 16: `TEMP_SUBCON*.csv’ неожиданная»

Это то, что у меня есть в настоящее время, когда строка 16 является первой строкой — Выше, это просто комментарии:

     if [[ ! -f $OUT_DIR -name TEMP_SUBCON*.csv ]] ; then
    exit $?
    fi
    
    TEMP_DATA_FILE=$(find $OUT_DIR -name TEMP_SUBCON_QTY_output*.csv)
    DATA_FILE=$(basename $TEMP_DATA_FILE | cut -c6-)
    
    echo $TEMP_DATA_FILE
    echo $DATA_FILE

## Rename the file name, remove the phrase TEMP_, so that EAI can pick the file ##
mv $TEMP_DATA_FILE $OUT_DIR/$DATA_FILE
 

Можете ли вы помочь понять, что я сделал неправильно?

Спасибо

Комментарии:

1. -f $OUT_DIR -name TEMP_SUBCON*.csv похоже , что он был снят с вызова find , для которого недопустим синтаксис [[...]] .

Ответ №1:

Если я правильно понимаю, вы хотите найти файлы с префиксом TEMP_ в вашем $OUT_DIR, а затем, если таковые имеются, переименовать их без префикса. Тогда это должно сработать

 for file in $OUT_DIR/TEMP_SUBCON_*.txt; do
    if [[ -e $file ]]; then
        mv $file $OUT_DIR/${file#*SUBCON_}
    fi
done
exit
 

Он будет проходить через каталог, находя каждый файл TEMP_, и переименовывать их без него. Если их нет, это ничего не даст.

Комментарии:

1. Спасибо @Andre Gelinas Попробовал это (Ну, немного измененная версия, так как она должна переименовывать только файлы, начинающиеся с TEMP_SUBCON, однако я получаю ошибку: mv: не удается указать «/opt/скрипты/данные/выход/TEMP_SUBCON*.csv»: Нет такого файла или каталога Какие-либо идеи?

2. хороший комментарий. Я отредактировал ответ.

3. Никаких ошибок, он ничего не переименовывал, а затем я понял, что выходные данные на самом деле .txt, поэтому я изменил файл .csv на .txt в приведенном выше примере, но теперь файлы просто исчезают. Если я удалю задание post, я увижу, что файлы созданы, но вместе с заданием они каким-то образом перемещаются или удаляются. Я попытался внести изменения в ваш код, чтобы иметь mv $file $OUT_DIR/${файл#*_} на случай, если они были записаны в другой каталог, но не повезло, тот же результат, файлы просто исчезают

4. можете ли вы привести реальный пример имен файлов ?

5. Конечно, имена файлов являются TEMP_SUBCON_DATE_output20210922.txt и TEMP_SUBCON_QTY_output20210922.txt

Ответ №2:

Этот синтаксис недопустим для [[ ... ]] теста.

Почему бы вместо этого не использовать результат последующей find команды, чтобы проверить, были ли какие-либо соответствующие файлы в указанном каталоге, и выйти, если файлы не возвращаются (другими словами, выйти, если переменная результата пуста)?

Пример:

 TEMP_DATA_FILE=$(find $OUT_DIR -name "TEMP_SUBCON_QTY_output*.csv" )
if [[ -z ${TEMP_DATA_FILE:=""} ]]  ; then
   exit 1
fi
 

Примечание 1: вы должны указать аргумент шаблона для find команды, как показано на рисунке.

Примечание 2 set -u .В ваших сценариях ksh полезно использовать для прерывания ksh , если при использовании переменные не инициализируются (часто это является причиной ошибок), вместо использования значения по умолчанию. Однако, если вы используете use set -u , то в любом тесте вы должны явно указать свое собственное значение по умолчанию. В этом причина использования ${TEMP_DATA_FILE:=»»} вместо ${TEMP_DATA_FILE} — для поддержки часто очень полезной set -u опции. Даже если вы не используете set -u ${TEMP_DATA_FILE:=»»} внутри тестов, это делает явным, что должно произойти, вместо того, чтобы полагаться на неявное поведение.

Примечание 3: вы должны использовать set -x при отладке и изучать каждую строку вывода, она покажет вам, какие именно команды выполнялись с какими аргументами и каков был результат. Это поможет вам научиться программировать в ksh и подобных оболочках.

Комментарии:

1. Спасибо @mao — я пробовал различные варианты из онлайн-руководств, и это было только мое последнее, поэтому не удивляюсь, что оно недействительно. Спасибо за пример, когда я пытаюсь, хотя он все еще ошибается, на этот раз он не выдает мне никакого сообщения об ошибке, оно просто отображается в журнале НЕУДАЧНО. Полный код теперь: TEMP_DATA_FILE=$(find $OUT_DIR -name TEMP_SUBCON_QTY_output*.csv) if [[ -z ${TEMP_DATA_FILE:=""} ]] ; then exit 1 fi DATA_FILE=$(basename $TEMP_DATA_FILE | cut -c6-) echo $TEMP_DATA_FILE echo $DATA_FILE mv $TEMP_DATA_FILE $OUT_DIR/$DATA_FILE exit $?

2. ${TEMP_DATA_FILE:=""} здесь немного странно. Нет смысла выполнять задание, если сценарий собирается завершиться, так что вы можете просто написать "${TEMP_DATA_FILE}"

3. Спасибо @WilliamPursell , попробовал с вашим предложением и тоже потерпел неудачу. Пример кода: TEMP_DATA_FILE=$(find $OUT_DIR -name TEMP_SUBCON_QTY_output*.csv) if [[ -z "${TEMP_DATA_FILE}" ]] ; then exit 1 fi DATA_FILE=$(basename $TEMP_DATA_FILE | cut -c6-) echo $TEMP_DATA_FILE echo $DATA_FILE ## Rename the file name, remove the phrase TEMP_, so that EAI can pick the file ## mv $TEMP_DATA_FILE $OUT_DIR/$DATA_FILE информация журнала больше не отображает ошибку, но отображает состояние «не удалось», в то время как я ожидал бы/нуждался в ней для успеха