Как вывести список файлов без каталогов и отфильтровать по имени (параметры ls)

42

У меня есть каталог под названием uploads. Он содержит несколько файлов, а также несколько подкаталогов, которые в свою очередь содержат файлы.

Есть ли способ, которым я могу (за один шаг) сделать следующее:

  1. Перечислять ТОЛЬКО файлы в корневом каталоге загрузок - я не хочу видеть имена подпапок или их содержимое;

    а также

  2. НЕ перечисляйте файлы, которые начинаются с t_

Я знаю о -dфлаге, но он не дает мне того, чего я хочу.

Emmys
источник

Ответы:

53

Это звучит как работа для find.

  • Используйте -maxdepthтолько для возврата текущего каталога, а не для рекурсивного поиска внутри подпапок
  • Используйте -type fтолько для возврата файлов, а не каталогов или узлов устройства или чего-либо еще
  • Используйте комбинацию if -notи, -nameчтобы избежать файлов с именами, которые вы не хотите

Это может сложиться так:

find /path/to/uploads -maxdepth 1 -type f -not -name 't_*'
Калеб
источник
Благодарность! Я довольно новичок в CLI и никогда раньше не использовал find. Я определенно буду смотреть дальше.
EmmyS
2
@EmmyS: Вы можете найти еще один полезный трюк здесь. @ Жиль упомянул об использовании -exec ls -lG -- {} +в своем ответе, чтобы получить вывод, используя дополнительные опции для ls. Вы также можете добавить просто -lsк этой находке, чтобы получить быстрое и грязное приближение подробного представления ls.
Калеб
18

GNU ls (т. Е. Команда ls в не встроенных системах Linux и Cygwin, также доступная в некоторых других приложениях) имеет возможность скрыть некоторые файлы, основываясь на их именах. Там нет способа игнорировать каталоги, хотя.

ls --hide='t_*' uploads

Другой подход - сделать так, чтобы ваша оболочка соответствовала. Bash, ksh и zsh имеют шаблон отрицания !(t_*)для соответствия всем файлам, кроме соответствующих t*; в bash эту функцию нужно включить с помощью shopt -s extglob, а в zsh - с setopt ksh_glob. Zsh также имеет эквивалентный синтаксис, ^t_*который необходимо включить setopt extended_glob. Это все еще не игнорирует каталоги. В Zsh есть дополнительная функция, которая позволяет сопоставлять файлы не только по имени, но и по метаданным и многим другим: квалификаторы glob . Добавить (.)в конце матча, чтобы ограничить обычные файлы. Отрицание ^является частью синтаксиса сопоставления имен, поэтому ^t_*(.)означает «все обычные файлы не совпадают t_*», а не «все файлы, которые не сопоставляются обычным файлам t_*».

setopt extended_glob  # put this in your ~/.zshrc
ls uploads/^t_*(.)

Если вы оказались без продвинутых инструментов, вы можете сделать это на любом Unix с find. Это не та вещь, которую вы обычно печатаете в командной строке, но она мощная и точная. Калеб уже показал, как это сделать с помощью GNU find . -maxdepthВариант не является переносимым; Вы можете использовать -pruneвместо этого, чтобы остановить findпереставая.

find uploads/* -type d -prune -o \! -type f -name 't_*' -print

Замените -printна, -exec ls -lG -- {} +чтобы выполнить lsваши любимые параметры файлов.

Все команды выше скрывают точечные файлы (то есть файлы, чье имя начинается с a .). Если вы хотите отобразить их, перейдите -Aк lsили добавьте Dквалификатор glob в zsh ( ls uploads/^t_*(.D)). С помощью findвы можете использовать другой подход, заставляя его повторять только один уровень (специально findне обрабатывает точечные файлы). Это полностью работает, только если вы работаете findв текущем каталоге.

cd uploads && find . -name . -o -type d -prune -o \! -type f -name 't_*' -print
Жиль "ТАК - перестань быть злым"
источник
3
У тебя есть дневная работа? ;-) Я постоянно удивляюсь длине и уровню детализации ваших ответов, даже на самые простые вопросы здесь, в Unix SE! .. Так или иначе, так держать! :)
Alex
Благодарность! Отличная деталь Я не знаю, есть ли у меня «продвинутые инструменты» или нет сейчас; Я нахожусь на Mac на работе (хотя Linux дома, поэтому я уверен, что это пригодится в какой-то момент.)
EmmyS
@EmmyS: Для вашей Linux-системы мое использование -maxdepthдолжно сработать, но проблема «переносимости», на которую ссылается Жиль, заключается в том, что BSD find(также найденный в OSX, я думаю) - это немного другое животное, так что вам может понадобиться и его ответ. @ Жиль: +1 за трюк Zsh!
Калеб
1
@Gilles: На pruneум приходят некоторые не очень сочные комментарии о s, но я позволю этому уйти, просто сказав, что когда я слоняюсь по своим системам, сколько раз мысль « сработает ли эта команда, если я буду на AIX, Solaris или MINIX3 "примерно ... в режиме ожидания ... Мне трудно получить показания счетчика ... дисплей завис 0.00.
Калеб
2
У Гну lsнет --use-telepathyвыбора? Это самый быстрый способ отобразить только те файлы, которые вы хотите. Это может быть не портативным, хотя.
dubiousjim
8
ls -l /folder | grep ^- | awk '{print $9}'
Krayher
источник
Что $9в этом утверждении?
EmmyS
3
@EmmyS Это означает 9-е поле / столбец вывода. Этот ответ пытается разобрать lsвывод .
jw013
print $ NF` будет лучше, ИМО. $ NF означает количество полей, которое будет равно 9 и является обычным использованием в AWK как хорошая возможность рассказать другим о $ NF.
Элайджа Линн
1
ls -l | grep -v ^d | grep name$
РИКАРДО МАРМОЛЕЙО ГАРСИЯ
источник
Что могло бы сделать это решение (которое требует нескольких команд и каналов) более предпочтительным find?
HalosGhost
Он лаконичен, легко читается и соответствует правилам команды ls. Мне легче запомнить, чем аргументы команды find. Каждому свое и благодарность за варианты!
tkjef
0

Позвольте мне дать ему шанс, используя lsи трубы:

ls  -l --hide='t_*'  uploads/ | grep -v ^d | tr -s ' ' | cut -d ' ' -f 9

скажем, последний столбец 9-й.

Y0NG
источник
1
Что делать, если есть файлы с пробелами?
Иордания
0

Если проблема переносимости find -maxdepth является проблемой, вы можете использовать:

ls -l uploads/ | awk '/^-/ && $9 !~/^t_/ {print $9}'

Я не эксперт, но я думаю, что это должно работать. Я полагаю, это выглядит немного загадочно, но если вы говорите на awk, это действительно не так. $ NF можно использовать вместо $ 9. Вы также можете сделать:

ls -l uploads/ | awk '/^-/' | awk '!/^t_/ {print $9}'

который делает то же самое (но, возможно, менее эффективно, чем первый ???).

На самом деле, подумав о других постах, выглядит

ls -l --hide=t_* uploads/ | awk '/^-/ {print $9}'

это еще короче и яснее.

Кто-нибудь, пожалуйста, поправьте меня, если я ошибаюсь. :-)

kkaszub
источник
Разбор, lsкак правило, не очень хорошая идея . Ваши трюки на awk потерпят неудачу с именами файлов, например, с пробелами в них.
Мат
@mat - Спасибо за исправление. Прочитав статью, которую вы (и jw013) указали, я вижу, что ls нельзя доверять для вывода правильных имен файлов. Даже если бы я переписал код awk для вывода всего от $ 9 до конца строки (включая пробелы), этот вывод ls все равно может быть ошибочным. Это разочаровывает и должно быть исправлено IMO. Еще раз спасибо.
kkaszub
0

Я нашел эти короткие пути:

ls -p uploads | grep -Ev '/'

или

ls -pIt_* uploads | grep -v /
Раду Рэдяну
источник
-1

Попробуйте этот псевдоним и используйте его:

alias l='ls -hLlF'
зернистый
источник
ls -hLlFпоказывает подкаталоги и показывает файлы, начинающиеся с t_. Так как же это ответить на вопрос?
Рафаэль Аренс
Возможно, я неправильно понял вопрос. ls -hLlF не будет показывать целевые каталоги связанных каталогов.
Гранулированный
Кажется, так. Но разве вы не читали другие ответы на вопрос?
Рафаэль Аренс
-1

Очень просто:

ls -l --hide 't_*' <absolute path to desired directory> | grep -v ^d

копатель
источник
(1) Этот ответ очень прост, он был дан раньше. (2) Почему вы считаете, что вам нужно указать полный путь к каталогу?
Скотт
@Scott - это очень быстрый и простой способ найти решение. Полный путь был указан, чтобы сделать ответ универсальным ...
Копатель