Intereting Posts
Как я могу переименовать каталог с именем, состоящим только из непечатаемых символов Можно ли сделать так, чтобы zsh-up-arrow поиска истории обнаруживал псевдонимы? В частности, удалите файлы, начинающиеся с ._, используя терминал Как разработать небольшой дистрибутив linux? PostgreSQL, доступный для веб-приложений Как подсчитать общее количество уникальных строк из файла с помощью linux Браузер Firefox плохо работает с мультимедиа, Fedora 22 Как предотвратить передачу прерывания клавиатуры через программу Screen Неоднократно извлекает каждую вторую и третью строки файла с 3-строчными блоками данных Дата и время создания группы томов LVM Fedora: выбранные горячие клавиши Lenovo, не работающие на Fedora 26 (keycode> 255) Как создать файл и родительские каталоги в одной команде? ничего не записывается в текстовый файл, если вы запускаете из cron Как скопировать AltGr + любую клавишу в ярлык в файле Openbox / Lubuntu lubuntu-rc.xml X11 мгновенно замораживается при сдвиге-3

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

У меня есть команда 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' 

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

Другие уже объяснили, что делать. Позвольте мне объяснить, что здесь происходит: символ трубы | не создает конвейер по мере расширения переменной, но действует как буквенный символ. Поэтому 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 $@"