Хорошо, давайте вернемся и посмотрим, что вы пытаетесь сделать. Первое, что нужно понять, это то, что вы не хотите проверять, является ли имя файла «*.txt
», вы хотите увидеть, соответствует ли оно шаблону «*.txt
». Кроме того, есть несколько различных шаблонов, с которыми вы столкнетесь в сценариях Unix; наиболее распространенными являются подстановочные знаки (или шаблоны "glob" )и регулярные выражения (, а также существует ряд версий синтаксиса регулярных выражений ). Здесь у вас есть шаблон глобуса.
Итак, вам нужен инструмент, который выполняет сопоставление шаблонов. (Ну,вы также можете переписать шаблон с другим синтаксисом или использовать совершенно другой подход к проверке расширения; но давайте пока остановимся на сопоставлении шаблонов глобусов.)
Во-вторых, вы используете это в операторе if
. Условное в операторе if
(вещь между if
иthen
)является командой(или, по крайней мере, командой -, подобной вещи ). Оператор if
зависит от того, будет ли эта команда выполнена успешно или нет. Одной из наиболее часто используемых команд в операторах if
является [
, которая представляет собой команду, подобную этой:
if [ "$file" = "*.txt" ]; then
[
выглядит как какой-то синтаксис оболочки или странная скобка, но это не так, это обычная команда (, в основном эквивалентная команде test
). Но это обычная команда, которая требует, чтобы ее последний аргумент был снова " ]
" (, не совсем закрывающая скобка, просто обычный аргумент команды ), и анализирует остальные аргументы как логическое выражение. См. man [
для его синтаксиса. Кроме того, обратите внимание, что я дважды -цитировал как "$file"
, так и "*.txt"
, потому что (в качестве обычных аргументов команды )имя файла будет подвергаться разбиению на слова, и они оба будут подвергаться расширению с помощью подстановочных знаков, что может сеять хаос с синтаксисом выражения.
Но [
не выполняет сопоставление с образцом. Он может выполнять строковые и числовые (целочисленные )сравнения, но не сопоставление с образцом. Поэтому нам нужно искать в другом месте.
Если вы используете bash (или zsh или даже ksh, но не dash или другую более простую оболочку ), вы можете использовать [[ ]]
. В отличие от [
, этот представляет собой синтаксис оболочки вместо обычной команды и, по сути, является очищенной -и обновленной заменой [
. И он может выполнять сопоставление с образцом с оператором =
, если вы оставите правую часть без кавычек. То есть,это будет выполнять буквальное сравнение строк:
if [[ "$file" = "*.txt" ]]; then
И это будет выполнять исправление шаблона глобуса:
if [[ "$file" = *.txt ]]; then
(Обратите внимание, что на самом деле вам не нужно удваивать -кавычки $file
для любого из них, но я предпочитаю автоматически удваивать -ссылки на переменные кавычек на том основании, что почти всегда безопасно удваивать -заключать их в кавычки, часто небезопасно оставлять их без кавычек, и легче запомнить исключения, в которых они должны быть не в кавычках, чем те, где они должны быть в кавычках.)
Итак, эта последняя команда является возможным ответом для вас при условии , что вы используете оболочку, которая поддерживает [[ ]]
(, т.е. если вы используете bash shebang, например #!/bin/bash
или #!/usr/bin/env bash
, не общий sh ).
Если вы используете простую sh
, нам придется немного изменить правила. Самый простой способ выполнить сопоставление шаблонов с подстановочными знаками в общей оболочке POSIX — использовать case
вместо if
. И это нормально, потому что сопоставление шаблонов с подстановочными знаками — это то, для чего case
был создан :
case "$file" in
*.txt )
echo "File is in correct format." ;;
* )
"File is not in correct format. Please recheck your file." ;;
esac
Обратите внимание, что шаблон *
(, который соответствует всему, что не соответствует более раннему шаблону ), действует подобно предложению else
в операторе if
. Кроме того, к синтаксису нужно немного привыкнуть: )
между каждым шаблоном и командой (s )для выполнения, если он совпадает, и ;;
в конце команд каждого шаблона.
Есть и другие варианты, если мы переключимся с «Я хочу сопоставить шаблон глобуса» на «Я хочу увидеть, заканчивается ли имя файла на '.txt'». Есть несколько (POSIX -стандартных )способов сделать это с помощью модификаторов расширения имени файла. Например, ${var%pattern}
удалит совпадение pattern
с конца значения переменной (, если соответствует ). Итак, один из стандартных приемов — попытаться удалить «.txt» в конце имени файла и посмотреть, изменилось ли оно. Если да, то ".txt" совпадал; если нет, то не было.Вот так:
if [ "$file" != "${file%.txt}" ]; then
Обратите внимание, что здесь используется проверка не -равенства (!=
), потому что строки будут отличаться только в том случае, если «.txt» был успешно удален с конца.
Вы также можете удалить последний "." в имени файла с${file##*.}
(и посмотрите, осталось ли «txt» ), но проблема в том, что он будет думать, что имя файла «txt» совпадает. Упс.
Для поиска доступных пакетов используйте:
opkg list | grep package
или
opkg list *package*
search
использование вopkg
:
opkg search file
Список пакетов, предоставляющих file
.
opkg
справочные страницы:
search <file|regexp> List package providing <file>
Команда opkg search
ошибочно заявляет, что ожидает регулярное выражение regexp (). На самом деле он ожидает подстановочный знак оболочки glob (). Кроме того, шаблон во многом соответствует всему пути и ищет только в базе данных установленных пакетов.
Итак, в одном из моих QNAP
opkg search /opt/bin/find # "findutils - 4.7.0-1"
opkg search find # no match
opkg search '*/find' # "findutils - 4.7.0-1"
Но
opkg search '*/ls' # no match, because coreutils-ls is not installed
Если вы хотите узнать, какой пакет содержит файл, сделать это не так-то просто. Вы можете искать имена пакетов,
opkg list | grep vi
opkg list | awk '$1 ~ /\<vi/'
или искать визуально,
opkg list | sort | cut -c1-80 | less