ldd vs rpm -q --требуется

Непосредственной проблемой в вашем коде является синтаксическая ошибка при чтении строки

if [` $x -eq 0 `]

[и ]должны быть отделены от аргументов внутри символом пробела. Кроме того, подстановка команды в этой строке, `$x -eq 0`, не имеет смысла, так как она будет пытаться запустить значение $xкак команду.

У вас также есть проблемы с не -заключением в кавычки ваших расширений переменных, что лишает ваш сценарий возможности работать с именами файлов, содержащими символы пробела и шаблоны подстановки имен файлов.

Сценарий также безоговорочно затирает файл newfileбез необходимости (и завершится ошибкой, если newfileявляется именем существующего каталога )и в нем отсутствует строка #!-.


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

.

$./script.sh some/path/file1 some/other/path/file2

Если запустить скрипт таким образом, два пути будут доступны внутри скрипта как "$1"и "$2".

Утилиту cmpможно использовать в этом скрипте без создания временного файла. Вместо перенаправления его вывода сделайте его тихим, используя параметр -s(для «тихого» )и используйте его статус выхода, чтобы определить, идентичны ли два файла или нет.

Скрипт будет выглядеть так

#!/bin/sh

if cmp -s -- "$1" "$2"; then
    rm -i -- "$2"
fi

Или, короче,

#!/bin/sh

cmp -s -- "$1" "$2" && rm -i -- "$2"

Это вызовет rm -iдля второго из двух заданных путей, если он ссылается на файл с идентичным содержимым, что и первый путь. Параметр --в командах cmpи rmнеобходим, чтобы избежать интерпретации имени файла, начинающегося с дефиса, как набора параметров.

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

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

Это можно сделать, сравнив две строки имени пути друг с другом:

#!/bin/sh

if [ "$1" != "$2" ] && cmp -s -- "$1" "$2"; then
    rm -i -- "$2"
fi

Этого может быть достаточно для большинства приложений, но не учитываются символические ссылки. В некоторых оболочках вы также можете использовать нестандартный --efтест («равный файл» ), который проверяет, относятся ли два пути к одному и тому же файлу (один и тот же i -номер узла и устройство):

#!/bin/bash

if ! [ "$1" -ef "$2" ] && cmp -s -- "$1" "$2"; then
    rm -i -- "$2"
fi

или,

#!/bin/bash

! [ "$1" -ef "$2" ] && cmp -s -- "$1" "$2" && rm -i -- "$2"

И с некоторыми проверками работоспособности (также перемещение теста -efв раздел проверок работоспособности):

#!/bin/bash

if [ "$#" -ne 2 ]; then
    # did not get exactly two arguments
    printf 'Usage:\n\t%s file1 file2\n' "$0" >&2
    exit 1
elif [ ! -f "$1" ] || [ ! -f "$2" ]; then
    echo 'One of the files does not exist (or is not a regular file)' >&2
    exit 1
elif [ "$1" -ef "$2" ]; then
    printf '%s and %s refer to the same file\n' "$1" "$2" >&2
    exit 1
fi

cmp -s -- "$1" "$2" && rm -i -- "$2"

Обратите внимание, что заключение расширений переменных в кавычки важно, так как имена путей нередко содержат пробелы (в macOS, это очень распространено ). Расширения переменных в двойных кавычках также предотвращают их интерпретацию как шаблоны подстановки оболочки (ваш код, например, не будет работать с файлом с именем*). Также обратите внимание на использование строки #!-, соответствующей сценарию.

Если ваше домашнее задание требует чтения путей к двум файлам в интерактивном режиме, сделайте это с read -rи с IFS, установленными в пустую строку. Это позволит вам читать пути, начинающиеся с пробелов и содержащие \символов :

.

#!/bin/bash

IFS= read -p '1st pathname: ' -r p1
IFS= read -p '2nd pathname: ' -r p2

if [ ! -f "$p1" ] || [ ! -f "$p2" ]; then
    echo 'One of the files does not exist (or is not a regular file)' >&2
    exit 1
elif [ "$p1" -ef "$p2" ]; then
    printf '%s and %s refer to the same file\n' "$p1" "$p2" >&2
    exit 1
fi

cmp -s -- "$p1" "$p2" && rm -i -- "$p2"

Связанные:


Если вам в какой-то момент нужно проверить, пуст ли файл, как в вашем собственном коде, то не вызывайте для него wc(это неэффективно, так как придется читать весь файл ). Вместо,используйте тест -s:

if [ -s "$pathname" ]; then
    printf '%s has non-zero size\n' "$pathname"
else
    printf '%s is empty (or does not exist)\n' "$pathname"
fi

См. man testв вашей системе или обратитесь к стандарту POSIX для этой утилиты .

0
12.01.2021, 18:02
1 ответ

lddперечисляет все требуемые библиотеки, включая те, которые требуются транзитивно. В метаданных RPM перечислены только прямые зависимости:

$ readelf -d /usr/bin/curl | grep NEEDED
 0x0000000000000001 (NEEDED)             Shared library: [libcurl.so.4]
 0x0000000000000001 (NEEDED)             Shared library: [libssl3.so]
 0x0000000000000001 (NEEDED)             Shared library: [libsmime3.so]
 0x0000000000000001 (NEEDED)             Shared library: [libnss3.so]
 0x0000000000000001 (NEEDED)             Shared library: [libnssutil3.so]
 0x0000000000000001 (NEEDED)             Shared library: [libplds4.so]
 0x0000000000000001 (NEEDED)             Shared library: [libplc4.so]
 0x0000000000000001 (NEEDED)             Shared library: [libnspr4.so]
 0x0000000000000001 (NEEDED)             Shared library: [libpthread.so.0]
 0x0000000000000001 (NEEDED)             Shared library: [libdl.so.2]
 0x0000000000000001 (NEEDED)             Shared library: [libz.so.1]
 0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]

Приведенная выше команда выводит список библиотек, объявленных как зависимости самим двоичным файлом. Это соответствует списку зависимостей (вместе с символами версий, см. readelf -V). Все остальные библиотеки, показанные в ldd, являются транзитивными зависимостями.

Зависимости транзитивных библиотек отражаются в зависимостях транзитивных RPM; например, библиотеки Kerberos подтягиваются libcurl.so.4и появляются в метаданных libcurl.

4
18.03.2021, 22:37

Теги

Похожие вопросы