Назад | Перейти на главную страницу

Bash-скрипт: проблема сравнения путей

Я работаю над сценарием bash, который перебирает список файлов. Мне нужно сравнить пути к этим файлам с массивом, содержащим ограниченные пути.

Внутри цикла for я получаю такой путь к файлу:

dname="$(dirname "$i")";

Это возвращает мне относительный путь, например путь / к / файлу

Список запрещенных путей хранится в массиве:

restricted=(
   path/to/file
   another/path/to/file
);

Потом пытаюсь сравнить пути:

if [[ "${restricted[*]}" = "$dname" ]]; then

//do some things

fi

Однако сравнение, похоже, не работает.

Не могли бы вы посоветовать, как решить проблему?

Спасибо.

Вам нужно перебрать элементы массива, например,

for i in "${restricted[@]}"
do
    if [ "$i" == "$ddame" ] ; then
        echo "Found"
    fi
done

Ответ Иана - официальный и лучший. Я пишу сценарии именно этим. Однако есть альтернатива. В этом нет ничего плохого с большой буквы, но я бы все равно не рекомендовал это.

if $(echo "${restricted[@]}" | grep -sw "${dname}") ; then
      echo "found"
 else
      echo "not found"
fi

Это повторяет ваш массив, передает вывод в grep, который будет соответствовать только целому слову (-w) и не будет выводить (-s), вместо этого указывая через код выхода, что совпадение было / не было. Этот код выхода - это то, что вы используете в качестве теста для оператора if.

Обратите внимание, что этот метод имеет ту же явную проблему, что и ваш =~ пример, который вы отправили для имени файла. Он будет соответствовать каталогам, которые содержат вашу строку в качестве подкомпонента. например: / путь / к / файлу / подпапке и / usr / local / путь / к / файлу оба будут совпадать. (Косые черты считаются разделителями, отличными от слов, для grep -w) Селектор частичного совпадения =~ вы используете для своих имен файлов будет такая же проблема.

Вы не можете напрямую сравнивать массив с переменной; он расширяется до:

[ "one two three" = "two" ]

Глядя на это, я уверен, что вы видите проблему!

Возможно:

case "${restricted[*]}" in
$ddname|* $ddname|* $ddname *|$ddname *)
    # do something
    ;;
esac

Непроверенные, вам могут понадобиться котировки на тестовой строке.

В противном случае итерация - единственный метод.