Список только обычных файлов (но не каталогов) в текущем каталоге

126

Я могу использовать, ls -ld */чтобы перечислить все записи каталога в текущем каталоге. Есть ли такой же простой способ просто перечислить все обычные файлы в текущем каталоге? Я знаю, я могу использовать найти

find . -maxdepth 1 -type f

или стат

stat -c "%F %n" * | grep "regular file" | cut -d' ' -f 3-

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

Даниэль Куллманн
источник
5
Что вы подразумеваете под "чрезмерно элегантным"? Насколько я знаю, findкоманда - лучший способ сделать то, что вы хотите. Для некоторых других надежных опций вы должны изучить команды, специфичные для оболочки (и это не портативные программы)!
Рахму
@rahmu Я был за что-то похожее ls -d */, короткое, легко набираемое и понятное. Так что я очень доволен ответом Ульриха Дангела, хотя я не использую zsh.
Даниэль Куллманн

Ответы:

32

С помощью zshи Glob Qualifiers вы можете легко выразить это напрямую, например:

echo *(.)

будет либо только возвращать список обычных файлов, либо ошибку в зависимости от вашей конфигурации.

Для не-каталогов:

echo *(^/)

(будет включать символические ссылки (в том числе на каталоги), именованные каналы, устройства, сокеты, двери ...)

echo *(-.)

для обычных файлов и символических ссылок на обычные файлы.

echo *(-^/)

для не-каталогов и никаких символических ссылок на каталоги.

Кроме того , см Dглобирования спецификатора , если вы хотите включить D от простых файлов (скрытые файлы), как *(D-.).

Ульрих Дангел
источник
170
ls -p | grep -v / 

Эта команда выводит список всех не скрытых файлов, которые не являются каталогами (обычные файлы, ссылки, файлы устройств и т. Д.). Чтобы также включить скрытые файлы, добавьте -Aпараметр вls

Предполагается, что ни один из файлов не имеет символов новой строки в своем имени. Добавление -qопции для lsпреобразования всех непечатаемых символов, включая символ новой строки ?, гарантирует, что они находятся в одной строке, и, таким образом, подходит для подачи в утилиту на основе строки, например, grepи для печати на терминале.

Атул Биджу
источник
14
+1, это хороший ответ. Вниз голосование нового пользователя без комментариев довольно шокирует меня, особенно когда предоставляется рабочий ответ. Единственный крайний случай, который я вижу, где это не будет работать должным образом, - это наличие новой строки в имени файла. Также сохранение цветов было бы хорошим дополнением, если поддерживается. Для GNU вы можете добавить --color=alwaysк ls, для OSX -G.
Грэм,
Привет, команда, которую вы дали, великолепна, и она, безусловно, выручает меня, однако мне было интересно, можно ли использовать вышеуказанную команду и одновременно изменить разрешение на доступ к файлу? Я попытался добавить в sudo chmod 777конце, и мне дали ошибки ... Любая помощь очень ценится
диссидия
3
Если вы также хотите исключить символические ссылки, которые указывают на каталоги, сделайте ls -pL | grep -v /. Добавлены -Lразыменования символических ссылок.
Матиас Браун
1
Если вам также нравится использовать подстановочный фильтр, сделайте ls -pdL something* | grep -v /. В добавленной -dопции перечислены сами каталоги, а не их содержимое, поэтому они будут исключены правильно.
Rockallite
И если вы хотите захватить все файлы без папок, просто удалите -v
jasonleonhard
23

Для просмотра только обычных файлов:

ls -al | grep '^-'

С символическими ссылками (на любой тип файла) включены:

ls -al | grep '^[-l]'

Где первый символ списка описывает тип файла, это -означает, что это обычный файл, для символической ссылки есть l.

Debian / Ubuntu

Напечатайте имена всех подходящих файлов (включая ссылки):

run-parts --list --regex . .

С абсолютными путями:

run-parts --list --regex . "$PWD"

Напечатайте имена всех файлов, /etcкоторые начинаются с pи заканчиваются на d:

run-parts --list --regex '^p.*d$' /etc
kenorb
источник
15

lsу него нет возможности сделать это, но одна из приятных особенностей unix & linux заключается в том, что длинные и неэлегичные конвейеры можно легко превратить в сценарий оболочки, функцию или псевдоним. и они, в свою очередь, могут использоваться в конвейерах, как и любая другая программа.

(ПРИМЕЧАНИЕ. Существуют некоторые проблемы с областями действия для функций и псевдонимов. Сценарии доступны любому исполняемому файлу, который может их читать и выполнять. Псевдонимы и функции доступны только в текущей оболочке, хотя .profile / .bashrc и т. Д. Вложенной оболочки могут переопределять и, таким образом, сделать их доступными. Кроме того, сценарий может быть написан на любом языке - включая bash / sh, awk, perl, python и другие - в зависимости от того, какой из них лучше подходит для работы или с которым вы наиболее знакомы)

например

alias lsf='find . -maxdepth 1 -type f -print0 | xargs -0r ls'

Я добавил xargs, чтобы вы могли использовать все обычные lsопции, напримерlsf -lrS

Поскольку он использует find, все обычно скрытые точечные файлы будут отображаться, и все имена файлов будут иметь префикс ./ - это единственное отличие, которое вы заметите.

Вы можете исключить точечные файлы с помощью, ! -iname '.*'но тогда вам понадобится две версии псевдонима: одна отображает точечные файлы, а другая - нет.

alias lsf2='find . -maxdepth 1 -type f -a ! -iname '\''.*'\'' -print0 | xargs -0r ls'

В качестве альтернативы, если это lsfбыл сценарий, а не псевдоним, вы можете проанализировать параметры (возможно, с помощью getopts или / usr / bin / getopt или аналогичных) и исключить точечные файлы, если они -aотсутствуют.

саз
источник
-nameдостаточно, вам не нужно -iname.
Тотор
8
bash-4.2$ ls -F | grep -v '[/@=|]$' | more

Опция -F для ls добавляет * к исполняемым файлам, / к каталогам, @ к символическим ссылкам, = к сокетам и | в ФИФО. Затем вы можете использовать grep для исключения нестандартных файловых символов из вывода, и у вас есть файлы. Это будет работать в любой оболочке, а не только в Zsh.

Слабые стороны:

  1. Любой файл, имя которого оканчивается на @, =или |будет исключен (но вы не должны действительно есть файлы с этими символами в названии так или иначе)
  2. Это не исключает файлы устройств или некоторые экзотические типы файлов в некоторых системах, таких как двери.
  3. К любому исполняемому файлу будет добавлена ​​звездочка. Это можно было бы сделать, отправив команду sed для удаления любых символов «*» из вывода.
  4. Это не работает должным образом, если есть имена файлов, содержащие символы новой строки.
kurtm
источник
О системе я пишу это на 10% файлы имеют имена , содержащие =, @или |символы. =обычно встречается в maildir или именах файлов, которые имеют закодированную часть в формате base64 или в кавычках. @в определениях локалей, для адресов электронной почты и многого другого. Однако они редко появляются в конце имени файла. (например, только 31 из 2,2 миллионов в этой системе)
Стефан Шазелас
3

В руководстве указано, что опция «f» предназначена только для «обычного файла», а не для каналов, сокетов или блочных / символьных устройств, что означает, что вы уже делаете правильные вещи.

   -type c
          File is of type c:

          b      block (buffered) special

          c      character (unbuffered) special

          d      directory

          p      named pipe (FIFO)

          f      regular file

          l      symbolic link; this is never true if the -L option or the
                 -follow option is in effect, unless the symbolic link  is
                 broken.  If you want to search for symbolic links when -L
                 is in effect, use -xtype.

          s      socket

          D      door (Solaris)
маргаритка
источник
0

Это не особенно коротко, но вы можете превратить его в скрипт или псевдоним, если вам нужно быстро его вызвать. Используя команду ls в качестве входного массива, вызовите ls -ld для каждой записи, переданной в grep, чтобы исключить каталоги с выводом, отправленным в null, и в случае успеха повторить исходный ввод:

for list in `ls` ; do ls -ld $list | grep -v ^d > /dev/null && echo $list ; done ;

Вы можете инвертировать grep и условный вывод, те же результаты:

for list in `ls` ; do ls -ld $list | grep ^d > /dev/null || echo $list ; done ;
Дон Р
источник
\dev\null?!?!
manatwork
Связанный: unix.stackexchange.com/questions/128985/why-not-parse-ls
Кусалананда
0

Это немного старая тема, но самый чистый способ перечислять только файлы.

ls -al | grep '^-' | awk '{print $9}'
RJ
источник
1
Связанный: unix.stackexchange.com/questions/128985/why-not-parse-ls
Кусалананда
1
touch "some file name"чтобы увидеть быстрый контрпример
Джефф Шаллер
@JeffSchaller У вас есть правильная точка. Для этого как то так. ls -al | grep '^-' | awk '{ for(i=9; i<=NF; ++i) printf $i""FS; print "" }', должен обрабатывать файлы с пробелами в них.
RJ