Используйте переменную оболочки для выполнения команды

У меня есть команда unix в переменной, она выглядит так:

cmd="find /path/to/webpage -type f | grep -v .svn | xargs grep $@" `$cmd` find: paths must precede expression Usage: find [-H] [-L] [-P] [path...] [expression] 

Когда я пытаюсь выполнить команду $cmd в сценарии bash, это не сработает, однако, когда я копирую и вставляю ту же самую команду, она работает. Можете ли вы сообщить мне, что я делаю неправильно?

Я попытался поставить кавычки вокруг пути, такая же ошибка возникает

 cmd="find \"/path/to/webpage\" -type f | grep -v .svn | xargs grep $@" find: paths must precede expression Usage: find [-H] [-L] [-P] [path...] [expression] 

Когда я -type f параметр -type f , я получаю эту ошибку:

 cmd="find /path/to/webpage | grep -v .svn | xargs grep $@" find: invalid predicate `-v' 

Это заставляет меня думать, что труба не распознается. Что я могу сделать, чтобы заставить это работать?

3 Solutions collect form web for “Используйте переменную оболочки для выполнения команды”

Другие уже объяснили, что делать. Позвольте мне объяснить, что здесь происходит: символ трубы | не создает конвейер по мере расширения переменной, но действует как буквенный символ. Поэтому find выполняется со следующими аргументами:

 {"/path/to/webpage", "-type", "f", "|", "grep", "-v", ".svn", "|", ...} 

и он интерпретирует | как путь и жалуется, что он должен появиться перед выражением ( -type f ).

Другая большая ошибка заключается в том, что вы используете `$cmd` как единственную командную строку. Если $cmd (т. rm -rf / find ... ) преуспел и произвел вывод как rm -rf / , он будет выполнен от вашего имени. Всегда будьте осторожны, когда вы берете данные как код!

Улучшение 1. find ... | grep -v ... find ... | grep -v ... – это плохой способ исключить что-то из результата: find будет пересекать целые подкаталоги с именем .svn , создавать строки, только чтобы их выбросить позже. Почему бы не сказать, find нужно сделать это прямо?

 find path -type f | grep -v .svn # don't do this find path -name .svn -prune -o -type f -print # do this instead 

Улучшение 2. При объединении find и xargs всегда используйте -print0 в find и -0 в xargs :

 find path ... -print0 | xargs -0 -r grep ... # I'd also recommend -r 

или вы можете сделать это целиком в grep :

 grep --recursive --exclude-dir=.svn pattern path 

Если вы действительно хотите выполнить код в переменной, вы можете сделать это с помощью eval .

 cmd="find /path/to/webpage -type f | grep -v .svn | xargs grep something" eval "$cmd" 

Но поскольку вы пытаетесь передать аргументы с помощью $@ , вам нужна функция

 webgrep() { find /path/to/webpage -type f | grep -v .svn | xargs grep "$@" } 

Обратите внимание, что это будет иметь проблемы с любыми путями, которые включают символ пробела. И он должен будет отсканировать все содержимое каталогов .svn прежде чем игнорировать их. Лучше всего

 webgrep() { find /path/to/webpage -name .svn -prune -o -type f -exec grep "$@" {} + } 

Затем назовите его так

 webgrep PATTERN 

Попробуйте создать свою переменную следующим образом:

 cmd=$(find /path/to/webpage -type f | grep -v .svn | xargs grep $@) 

или

 cmd=`find /path/to/webpage -type f | grep -v .svn | xargs grep $@` 

Или, может быть, псевдоним лучше подходит:

 alias cmd="find /path/to/webpage -type f | grep -v .svn | xargs grep $@" 
  • как вывести вывод поиска в другой поиск
  • удалить дубликаты файлов
  • Исключить из подстановочного знака (*), используя find
  • найти поиск в родительских каталогах вместо подкаталогов
  • найти командную помощь
  • Как удалить старые файлы в папке в unix?
  • поиск и подглаживание (и подстановочные знаки)
  • Как удалить все внутри каталога, без конкретной папки и содержимого
  • Очистка содержимого файлов по размеру
  • находить и копировать файлы, используя список входных данных и частичные пути к файлам
  • Как распечатать совпадение, а также запустить -exec
  • Interesting Posts

    Что такое системный идентификатор раздела?

    Проверьте, является ли каталог точкой монтирования

    Возвышенная командная строка открывает его дважды

    создать маршрут после изменения pptp vpn ip

    проблема с конфигурацией интерфейса соединения с сервером

    Как программно определить установленную максимальную версию ядра RPM?

    Как повторно активировать службу удаленного рабочего стола «Нет машины» с помощью командной строки?

    Есть ли такая утилита, как `watch`, за исключением события?

    Почему postfix не проверяет отправителя, кто, как они говорят, использует обратные dns, SPF или DMARC?

    Как включить панель инструментов «Закладки» в Firefox 4?

    Почему мое монтирование привязки видимо за пределами пространства имен mount?

    Как правильно установить параметр команды ядра для sdboot

    Есть ли способ проверить, был ли .so скомпилирован флаг -Bsymbolic-functions?

    Как udev создает / dev / sr *? (Или: какое правило создает / dev / sr *?)

    Пользовательские данные в evince и cups

    Linux и Unix - лучшая ОС в мире.