Необходимо определить исполняемые файлы с помощью булевой оболочки тестового конструкта.

Вопрос или проблема

Я пытаюсь создать символические ссылки на исполняемые файлы в каталоге bin в скрипте Docker. Мне нужен способ идентифицировать исполняемые файлы и вернуть логический статус. Я пробовал это:

for i in ../src/u-boot/tools/*; do if ! [[ "readelf -h $i | grep -q DYN" ]]; then ln -s $i .; fi; done

Это не работает, и я не понимаю, почему.

Если я смотрю на фактические значения возврата, я вижу ожидаемые значения:

root@0f1bca692c90:/home/work/bin# readelf -h ../src/u-boot/tools/mkimage |grep -q DYN 
root@0f1bca692c90:/home/work/bin# echo $?
0
root@0f1bca692c90:/home/work/bin# readelf -h ../src/u-boot/tools/mkimage.c |grep -q DYN
readelf: Error: Not an ELF file - it has the wrong magic bytes at the start
root@0f1bca692c90:/home/work/bin# echo $?
1

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

Обновление

Мне удалось заставить это работать вот так:

RUN for i in ../src/u-boot/tools/*; do if /usr/bin/readelf -h $i | grep -q DYN; then ln -s $i .; fi; done

Проблема имеет несколько аспектов, но основной заключается в том, что вы выбрали конструкцию теста Bash [[ ... ]] и поместили условие теста полностью в двойные кавычки. Это означает, что вся условие интерпретируется как строка, которая, так как она непустая, всегда оценивается как “истинное”.

Второй момент в том, что вам на самом деле не нужна конструкция теста. Поскольку вы основываете свой тест на наличии свойства DYN в выводе readelf, которое вы проверяете с помощью grep, вы можете просто написать

if readelf -h "$i" | grep -q "DYN"
then
   ...
fi

Поскольку статус выхода конвейера команд является статусом последней команды в конвейере, вы получите “истинное”, если DYN был найден в выводе, и “ложное”, если DYN не был найден.

Последний момент может быть недопониманием значения $?. Для тестов в оболочке код выхода 0 означает истинное, в то время как ненулевой код означает ложное, поэтому отрицание (if ! ....), которое у вас было, (если я правильно понимаю ваше намерение) неверно на данный момент.

Ответ или решение

Для решения задачи определения исполняемых файлов в контексте использования readelf и grep необходимо учесть несколько моментов, касающихся работы с условиями в Bash и интерпретацией возвращаемых значений команд.

Проблема исходного кода

В вашем начальном коде:

for i in ../src/u-boot/tools/*; do
    if ! [[ "readelf -h $i | grep -q DYN" ]]; then
        ln -s $i .
    fi
done

вы столкнулись с ошибкой, потому что условие, обернутое в двойные кавычки внутри [[ ... ]], интерпретируется как строка. Это означает, что Bash всегда считает условие истинным (всегда возвращает 0), так как непустая строка имеет значение "true", а не результат выполнения команды readelf.

Решение с использованием if без

Для правильного определения исполняемых файлов можно упростить код, убрав лишнюю обертку в [[ ... ]] и сделав выполнение команд в условии:

for i in ../src/u-boot/tools/*; do
    if readelf -h "$i" | grep -q "DYN"; then
        ln -s "$i" .
    fi
done

В этом варианте:

  1. Проверка на наличие "DYN": Условие проверяет, содержит ли вывод команды readelf -h слово "DYN".
  2. Правильная интерпретация статусов: Так как статус выхода из grep будет 0, если "DYN" найден, условие будет истинным, и создастся символическая ссылка на исполняемый файл.

Возвращаемые значения

Важно помнить, что в Bash:

  • Статус 0 указывает на успешное выполнение (что соответствует "true").
  • Статус, отличный от 0, указывает на неудачу (что соответствует "false").

Следовательно, использование if ! ... в вашем исходном коде было ошибочным, так как вы имели в виду, что вы хотите выполнить действия, когда не найден "DYN".

Итоговая рекомендация

Постарайтесь привязаться к простоте и понятности. Следующий рабочий фрагмент кода выполнит необходимую задачу, корректно проверяя исполняемые файлы и создавая символические ссылки только для них:

for i in ../src/u-boot/tools/*; do
    if readelf -h "$i" | grep -q "DYN"; then
        ln -s "$i" .
    fi
done

Используя данный подход, вы сможете успешно идентифицировать исполняемые файлы и упростить процесс создания символических ссылок в вашем Docker скрипте.

Оцените материал
Добавить комментарий

Капча загружается...