Первый пример
$ ffind $intVal
'' is not a valid resource
Это не работает, потому что $foo является синтаксисом для переменных, и у вас нет переменной с именем intVal set, поэтому $intVal преобразуется в пустую строку. Поскольку переменная также не заключена в кавычки , аргументы вообще не передаются в ffind .
Чтобы исправить это, избегайте $ - \$intVal (обратный слеш) или '$intVal' (в одинарных кавычках).
Если у вас действительно есть переменная с именем intVal , вместо этого поместите ее в двойные кавычки - "$intVal" - это расширит значение переменной, но не разделит ее.
Обратите внимание, что в bash нет такой вещи, как "передать по ссылке". Существует только передача по значению и (хитрая) передача по имени.
Второй пример
$ ffind "testing :"
bash: [: testing: unary operator expected
'testing :' is not a valid resource
Это не работает, потому что вы забыли поместить кавычки около $1 в строку if [ $1 ] , поэтому он может быть разбит на слова , и три аргумента передаются в [ builtin:
- "
[ "
- "
testing "
- "
: "
- "
] "
вместо ожидаемых двух:
- "
[ "
- "
testing : "
- "
] "
Пример # 1 также зависит от этого, так как [ $1 ] распадается на ([ ] ") , а не [ "", Пример № 1 работает случайно, хотя, по-видимому, ] является действительным. (Я этого не знал ...)
Чтобы решить эту проблему, поместите двойные кавычки около $1 - [ "$1" ] .
Примечание. Хотя [ является стандартным, есть также специфический для bash оператор [[ , который на самом деле имеет правила синтаксического анализа, отличные от остальной части кода - в частности, он не разделяет расширенные переменные. В bash [[ $1 ]] и [[ "$1" ]] оба эквивалентны, в отличие от их [ альтернатив.
Больше ошибок
У вашей функции также есть несколько других проблем, которые не показаны в примерах.
find -type f | grep -ir '$1' * | grep -v '.svn'
В этой строке:
Слово '$1' заключено в одинарные кавычки. Это означает, что bash не будет расширять свое содержимое - вы фактически указываете grep искать регулярное выражение $1 , а не аргумент командной строки.
Чтобы исправить это, используйте двойные кавычки - "$1"
Первой команде grep предписывается рекурсивно искать содержимое всех файлов в текущем каталоге (-r и подстановочный знак *).
В то же время вы передаете вывод команды find -type f в grep - по-видимому, пытаясь заставить grep искать имена всех файлов.
Это не сработает, потому что grep , как и большинство фильтров, не будет читать со стандартного ввода, если ему будет предоставлен один или несколько файлов для поиска. Я не знаю, что вы пытаетесь найти - имена файлов или содержимое файлов - поэтому выберите один:
Чтобы искать только имена файлов, сохраните канал, но удалите спецификацию файла:
find -type f | grep -i "$1" | ...
Для поиска только содержимого файла удалите find| вместо:
grep -ir "$1" * | ...
Можно комбинировать оба, явно давая Grep файл "STDIN":
find -type f | grep -i "$1" - * | ...
find -type f | grep -i "$1" /dev/stdin * | ...
(/dev/stdin работает со всеми программами Linux, в то время как - это соглашение, используемое некоторыми программами, включая grep.)
Во второй команде grep регулярное выражение для поиска слишком широкое. (Помните, что это регулярное выражение, а не фиксированная строка.) .svn будет соответствовать даже чему-то вроде « not-a-svn-file ».
Чтобы исключить каталог .svn , используйте вместо него grep -v "/\.svn/" .
При поиске содержимого файла (grep -ir ...), даже лучше полностью избавиться от команды grep -v и добавить --exclude-dir=".svn" к первой.
Вы можете перестать читать на этом этапе
Приведенные ниже пункты являются хорошей практикой в сценариях sh .
Ключевое слово function является необходимым: ffind() { ... достаточно и работает во всех оболочках POSIX (в то время как function ffind не будет).
В случае сбоя скрипта, программы или функции он должен вернуть статус "сбой" своему родителю. По соглашению, программы Unix считают, что 0 означает "успех", а все остальное "неудача" (хотя есть и исключения из последних).
Чтобы явно вернуть состояние, используйте return <num> в функции (или exit <num> в автономном скрипте):
else
echo "'$1' is not a valid resource" >&2
return 1
fi
Аналогично, сообщения об ошибках не следует смешивать с обычным stdout, а вместо этого записывать в stderr (fd # 2), используя оператор перенаправления >& (см. Приведенный выше пример). Таким образом, вы можете перенаправить обычный вывод в файл (например, ffind intVal > results.txt), сохраняя ошибки на экране.
Фиксированный код
ffind()
{
if [ "$1" ] ; then
grep -ir --exclude-dir=".svn" "$1" .
else
echo "'$1' is not a valid resource" >&2
return 1
fi
}
Лучшие инструменты
ack утверждает, что он "лучше чем grep". Выполнение ack "testing :" будет искать ваш исходный код и автоматически пропускать .svn и подобные каталоги.