Список записей в каталоге с помощью grep

Я пытаюсь перечислить все записи в каталоге, имена которых содержат ТОЛЬКО заглавные буквы. Каталоги должны быть дополнены "/".

#!/bin/bash
cd ~/testfiles/
ls | grep -r *.*

Поскольку grep по умолчанию ищет только заглавные буквы (правильно?), я просто рекурсивно ищу в каталогах под тестовыми файлами все имена, которые содержат только заглавные буквы.

К сожалению, это не работает.

Что касается добавления каталогов, я не уверен, зачем мне это нужно делать. Кто-нибудь знает, с чего я могу начать с подробными объяснениями того, что я могу сделать с помощью grep? Кроме того, как решить мою проблему?


person user2001465    schedule 05.02.2013    source источник
comment
Хорошей отправной точкой является man grep :-/   -  person JohnTortugo    schedule 05.02.2013
comment
У меня есть, это действительно не дает мне много работы. Признаюсь, я новичок в этом, поэтому я не совсем уверен, что мне следует использовать для строки поиска. Д:   -  person user2001465    schedule 05.02.2013


Ответы (3)


Нет, grep учитывает не только прописные буквы.

Ваш вопрос мне немного неясен, например:

  • судя по тому, как вы используете опцию -r, вы хотите искать рекурсивно, однако вы этого не говорите. Для простоты я предполагаю, что вам это не нужно; рассмотрите возможность изучения ответа @twm, если вам нужна рекурсия.
  • вы хотите искать только прописные буквы (буквы). Означает ли это, что вы не хотите принимать какие-либо другие (не буквенные) символы, но которые до сих пор действительны для имен файлов (например, цифры или тире, точки и т. д.)
  • поскольку вы не говорите, что не разрешено иметь только один файл на строку, я предполагаю, что это нормально (таким образом, используя ls -1).

Наивным решением было бы:

ls -1 | grep "^[[:upper:]]\+$"

То есть выведите все строки, содержащие только заглавные буквы. В моем каталоге TEMP, который печатает, например:

ALLBIG
LCFEM
WPDNSE

Однако при этом будут исключены такие файлы, как README.TXT или FILE001, которые, в зависимости от ваших требований (см. выше), скорее всего, должны быть включены.

Таким образом, лучшим решением будет:

ls -1 | grep -v "[[:lower:]]\+"

То есть выведите все строки, не содержащие строчной буквы. В моем каталоге TEMP, который печатает, например:

ALLBIG
ALLBIG-01.TXT
ALLBIG005.TXT
CRX_75DAF8CB7768
LCFEM
WPDNSE
~DFA0214428CD719AF6.TMP

Наконец, чтобы «правильно пометить» каталоги символом «/» в конце, вы можете использовать опцию -F (или --classify).

ls -1F | grep -v "[[:lower:]]\+"

Опять же, пример вывода:

ALLBIG
ALLBIG-01.TXT
ALLBIG005.TXT
CRX_75DAF8CB7768
LCFEM/
WPDNSE/
~DFA0214428CD719AF6.TMP

Обратите внимание, что другим вариантом будет использование find, если вы можете жить с другим выходом (например, find ! -regex ".*[a-z].*"), но это будет иметь другой результат.

person Christian.K    schedule 05.02.2013
comment
Привет, Кристен. К. - Мне нравится твой ответ, спасибо. Это имеет смысл. Что именно делает параметр -1? - person user2001465; 06.02.2013
comment
Хм, я не уверен, что делаю что-то не так, но ваш ответ не работает, он также печатает строчные буквы. - person user2001465; 06.02.2013
comment
Может что-то не так - я сейчас не комп, завтра проверю. - person Christian.K; 06.02.2013
comment
Я считаю, что это должно быть «*» вместо «+» - person Satish; 06.02.2013

Точное регулярное выражение зависит от формата вывода вашей команды ls. Предполагая, что вы не используете псевдоним для ls, вы можете попробовать следующее:

ls -R  | grep -o -w "[A-Z]*"

обратите внимание, что с -R в ls вы будете рекурсивно перечислять каталоги и файлы в текущем каталоге. Параметр grep -o указывает grep печатать только совпавшую часть текста. Параметры -w говорят grep считать совпадением только целые слова. "[A-Z]*" — это регулярное выражение для фильтрации только слов в верхнем регистре.

Обратите внимание, что это регулярное выражение будет печатать TEST.txt, а также TEXT.TXT. Другими словами, он будет рассматривать только имена, состоящие из букв.

person JohnTortugo    schedule 05.02.2013

Это ls, в котором перечислены файлы, а не grep, поэтому вам нужно указать, что вы хотите, чтобы «/» добавлялся к каталогам. Используйте ls --classify для добавления "/" к каталогам.

grep используется для обработки результатов из ls (или, вообще говоря, из какого-либо другого источника) и показывает только те строки, которые соответствуют указанному вами шаблону. Он не ограничивается символами верхнего регистра. Вы можете ограничить его только символами верхнего регистра и «/» с помощью grep -E '^[A-Z/]*$ или, если вам также нужны числа, точки и т. д., вы можете вместо этого отфильтровать строки, содержащие символы нижнего регистра с помощью grep -v -E [a-z].

Поскольку grep - это не программа, которая выводит список файлов, это не то место, где вы хотите выполнить рекурсию. ls может отображать пути рекурсивно, если вы используете ls -R. Однако таким образом вы просто получите последний компонент путей к файлам.

Возможно, вы захотите использовать find для обработки рекурсии. Это работает для меня:

find . -exec ls -d --classify {} \; | egrep -v '[a-z][^/]*/?$'

Я должен отметить, что использование ls --classify для добавления «/» в конец каталогов может также добавлять некоторые другие символы к другим типам путей, которые он может классифицировать. Например, он может добавлять «*» в конец исполняемых файлов. Если это не нормально, но вы согласны с перечислением каталогов и других путей отдельно, это можно обойти, запустив find дважды - один раз для каталогов, а затем еще раз для других путей. Это работает для меня:

find . -type d | egrep -v '[a-z][^/]*$' | sed -e 's#$#/#'

find . -not -type d | egrep -v '[a-z][^/]*$'

person twm    schedule 05.02.2013