У меня были проблемы последние шесть месяцев или около того при объединении поисков в bash. Точный пример связан с программированием на Python, но применим к любому виду обнаружения / манипулирования.
Предположим, мне нужен список всех файлов Python в каталоге, где я нахожусь. Это легко:
find . -name '*.py'
Теперь предположим, что меня интересуют только те файлы Python, которые содержат строку «psycopg», например, потому что я хочу перейти от старой библиотеки доступа PostgreSQL psycopg к psycopg2 . Все еще достаточно просто:
grep -l psycopg `find . -name '*.py'`
Теперь, предположим, я хочу составить полный список этих файлов, чтобы проверить их штампы с датами, чтобы увидеть, когда я в последний раз касался их. Я мог бы также хотеть открыть их в gedit, но давайте придерживаться списка:
ls -l `!!`
, который расширяется до
ls -l `grep -l psycopg `find . -name '*.py'``
Теперь, что происходит? Ответ: ничего. Приглашение Bash просто висит. Это почему? Это может быть неправильный способ делать вещи, но раньше это работало. Я почти уверен, что он работал до Ubuntu 10.10 или 10.04.
Проблема заключается в замене вложенных команд обратными чертами. bash
сначала пытается выполнить grep -l psycopg
(который находится между первыми двумя обратными галочками). Но имени файла нет - поэтому он ожидает ввода на stdin
(вы можете попробовать это, введя psycopg
).
Вы можете избежать этой проблемы, используя синтаксис $(command)
для подстановок команд:
grep -l psycopg $(find . -name '*.py')
ls -l $(!!)
В этом случае он может быть вложенным.
Сделайте это, как правило, наоборот, найдите файлы, вставьте в них grep и используйте команды find ls:
find . -name '*.py' -exec grep -q psycopg {} ";" -ls
возможны специальные формы вывода (printf) и перечислены на странице поиска. .
Бэктикс не гнездится. Первая встроенная команда - grep -l psycopg
, которая собирается прослушивать данные в stdin, потому что нет имен файлов.
Я бы сказал, привыкли использовать $(this syntax)
вместо обратных кавычек, потому что они правильно вкладывают.
ls -l $(grep -l psycopg $(find . -name \*py))
Всегда неправильно иметь команды, которые выводят более одного имени файла внутри $()
или ``
(подстановка команд). См. http://mywiki.wooledge.org/ParsingLs для объяснения того, почему вы не должны этого делать.
Также прочитайте http://mywiki.wooledge.org/UsingFind и http://mywiki.wooledge.org/BashFAQ/020 о том, как использовать поиск и работу с имена файлов правильно.
И нет,
ls -l `grep -l psycopg `find . -name '*.py'``
не могли бы работать и в более ранних версиях.
Ответ неизвестного пользователя показывает хороший и безопасный способ выполнить задачу, о которой вы спрашивали.