Intereting Posts
Чтение / запись на необработанном изображении NTFS Перепутал файл .bashrc Что произойдет, если мы подключим файловую систему, в которой работает e2fsck? Префикс и добавление блоков текста в список файлов Отдельное рабочее пространство на монитор в XFCE tmux случайные символы, появляющиеся в терминале GTK_IM_MODULE = xim разрывает мертвые ключи в приложениях GTK и QT Как связать настройку конфигурации ядра с исходными файлами? «Не обычный файл» при попытке просмотреть файл .gitignore Текстовый почтовый клиент с удобством использования Gentoo и Systemd: Может ли openrc быть удаленным без нарушения других пакетов? Вывод нескольких строк из нескольких файлов Приоритет логических операторов по сравнению с точкой с запятой Получить контактную информацию системного администратора с терминала Как найти и переместить текстовую строку внутри файла?

найти и конвейер grep ничего не возвращает

У меня есть файлы с именем lect1.txt , lect2.doc и lect3.doc .

Я хочу получить файл, который является .txt файлом, и содержит в качестве имени файла.

Я пытался

 find *.txt | grep lect* 

и он ничего не возвращал.

но когда я это сделал

 find *.txt | grep "lect*" 

он возвратил lect1.txt .

В чем разница между этими двумя выражениями?

grep ищет первый аргумент (шаблон) в файлах, переданных в командной строке или stdin если файлы не переданы.

Без цитаты ваша оболочка будет расширять lect* во всех файлах в каталоге, которые начинаются с lect . Тогда ваша команда будет:

 grep lect1.txt lect2.doc lect3.doc 

что означает поиск текста lect1.txt в обоих файлах .doc . Если один из файлов .doc содержит в себе фразу lect1.txt , он ничего не вернет. Точнее, он будет искать lect1 за которым следует любой символ ( . ), За которым следует txt , поэтому он также найдет lect1-txt и lect1xtxt и lect1xtxt Д.),

В вашем втором примере вы процитировали "lect.*" Чтобы оболочка не расширила его и передается как в grep . Если только шаблон передан как аргумент, grep будет искать имена файлов, переданные в stdin для шаблона, что и есть то, что вы после того, как я верю.

find *.txt | grep lect*

Обычно вы хотите указать имя пути в качестве первого аргумента, чтобы find(1) , а не имя файла. Это, конечно, не шаблон имени файла. Оболочка расширяет *.txt в имя всех *.txt файлов в текущем каталоге перед вызовом find , который здесь не тот, который вам нужен.

Более полезными вариантами этой команды являются

 find . -name 'lect*' | grep 'txt$' 

или

 find . -name 'lect*txt' 

Также обратите внимание, что find(1) использует выражения glob в -name inname, тогда как grep(1) использует регулярные выражения . Это важно здесь, потому что * означает что-то немного другое в двух системах.

Реализации BSD и GNU find имеют нестандартный -regex primary, который позволяет вместо этого использовать регулярные выражения:

 find . -regex '.*/lect.*txt' 

Обратите внимание, что шаблон должен соответствовать всему пути, найденному find , поэтому нам нужен префикс .*/ , И нет необходимости привязывать txt к концу с помощью $ as с помощью grep .

Вы злоупотребляете find и это работает случайно. Вы видите – запустив:

 find *.txt 

То, что вы на самом деле делаете, вызывает:

 find lect1.txt 

И вы выполняете немного больше, чем echo . Если, однако, вы запустите find с критериями поиска – так например:

 find . -name '*.txt' 

Затем он пересечет текущий каталог . и распечатать любое имя файла, соответствующее спецификации в любом подкаталоге.

Следует проявлять осторожность, потому что «*», как интерпретируется find, * в оболочке и * в регулярном регулярном выражении различаются по смыслу.

Если вы grep ing * означает «ноль или более экземпляров предыдущего символа».

Итак, вы на самом деле:

  • повторяя все ваши имена файлов (globbing *.txt ).
  • grepping, чтобы печатать любые, которые соответствуют любым символам с lectt , lecttttttt , lectt , lecttttttt и т. д. посередине.

В вашем первом примере, однако, вы, grep, даже не догадались, что оболочка расширяет ваш шаблон, поэтому на самом деле grepping для всего, что соответствует echo lect* , может работать случайно, потому что у вас есть файл в вашем каталоге, который расширяется надлежащим образом, но он не делает то, что вы намеревались.

Я бы предложил вместо этого то, что вы хотите:

 find . -name 'lect*.txt' -print