Как отсортировать сначала каталоги, затем файлы и т. Д. При использовании «ls» в Unix

91

Я хотел бы использовать lsкоманду, чтобы сначала показать каталоги, а затем файлы. Я пытался:

ls -la | sort -k 1

Но я получил неправильный заказ.

atricapilla
источник
это потому, что -раньше dпри использованииsort
Nifle
4
Старые UNIX-заголовки (те, что были до эпохи GUI), использовались для того, чтобы использовать заглавные буквы в своих именах папок и делать простые имена файлов некапитализированными, чтобы получить этот результат автоматически.
JRobert
Полезный вопрос! Возможно, пришло время изменить принятый ответ на более простой и не нарушающий цвета терминала?
ippi
Попробуйls -lh --group-directories-first
Диого

Ответы:

28

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

ls -la | grep "^d" && ls -la | grep "^-" && ls -la | grep "^l"

Кроме того, имеет смысл создать псевдоним для этой команды, чтобы сохранить нажатия клавиш.

Редактировать:

Если вы хотите сначала каталоги, а затем все, что не является каталогом, используйте это:

ls -la | grep "^d" && ls -la | grep -v "^d"

eleven81
источник
1
Эта команда не выводит список всех, если в папке есть, например, сокеты или FIFO
Studer
1
Эта отредактированная версия все еще должна работать с другими типами. Первый grep говорит все, что начинается с «d», а второй говорит все, что не начинается с «d». Конечно, все либо начинается с рекламы, либо нет, верно?
Ry4an Brase
1
@Mark - Почему просто не делать: ls -la | grep "^d" && ls -la | grep "^-" && ls -la | grep -v -E "^d|^-|^total"?
FCTW
1
Чтобы сделать команду @ FCTW псевдонимом OSX, добавьте это в ваш ~ / .profile:alias la="ls -la | grep \"^d\" && ls -la | grep \"^-\" && ls -la | grep -E \"^d|^-\" -v | grep -v \"^total\""
aliteralmind
2
Я нашел рабочее сокращенное обозначение: ls -la|grep ^d;ls -la|grep -v ^d(кавычки не обязательны и заменены &&на ;). Другим вариантом является введение переменной , а затем оценить его: a="ls -la|grep ^d";eval $a;eval $a -v. Может быть полезно избежать повторений, когда в ls/ указано гораздо больше параметров grep. Есть и такой ls -la --group-directories-firstвариант, однако самое короткое из нихls -la|sort
Стивен Прибилинский,
205

Я так люблю * nix и люблю видеть изобретательность, которая входит в некоторые из этих ответов ...

Мой не так хорош в GNU Linux:

alias ls='ls --color -h --group-directories-first'

Учитывая, что мне больше нравится работать с Linux-приложениями CLI, я также склонен обновлять coreutils в OSX:

brew install coreutils
alias ls='/usr/local/bin/gls --color -h --group-directories-first'
jonathanserafini
источник
6
к сожалению, это не работает на терминале osx, так как опция - недоступна.
MEM
7
re love: это сарказм? Если так, я бы согласился.
allyourcode
4
Цель псевдонима ls - определить элементы конфигурации, которые я хочу использовать 90% времени. Меньше нажатий клавиш для достижения желаемого результата. Если вам когда-нибудь захочется иметь собственный вывод ls, вы всегда можете / bin / ls.
Джонатансерафини
4
@MEM Если вы используете OS X и вам нравится использовать Terminal, то вы должны brew install bash тогда, это будет работать! :)
Эндрю Ашбахер
5
Мое мнение: это должен был быть принятый ответ, поскольку в нем перечислены параметры командной строки для достижения именно цели, а не запутанного набора grep и т. Д.
Райан Григгс
17

Для пользователей Mac coreutils :

brew install coreutils

alias ls='ls --color -h --group-directories-first'

Предполагая, что ваша система готова к домашнему пиву :

Вадим Тюмиров
источник
7
glsскорее. Правильно?
Пол Ирландский
1
Да, по умолчанию. Вы также можете использовать coreutils по умолчанию с PATH="/usr/local/opt/coreutils/libexec/gnubin:$PATH".
Бенеш
7

Есть некоторые вещи, которые я хочу видеть в списке каталогов, и пока ни один из ответов здесь не отвечает всем требованиям ниже. Мои требования к списку каталогов:

  1. Каталоги и файлы отсортированы в алфавитном порядке
  2. Каталоги перечислены первыми
  3. Символьные ссылки (символические ссылки) сортируются как файлы
  4. Сортировка нечувствительна к регистру
  5. Сортировка игнорирует все начальные не-буквенные символы в имени файла
  6. Список включает в себя общее количество каталогов (за исключением ./и ../), файлов и ссылок
  7. Список включает в себя общий размер (использование диска) каталогов и файлов
  8. Список должен выглядеть одинаково для Linux и Windows (оболочка Git Bash) - это было труднее всего получить, так как удобные опции, такие как --group-directories-firstне работать в Git Bash для Windows

После долгих взломов я наконец-то придумал однострочник (хотя и очень длинную линию ;-)), которым я доволен. Я назначил это псевдониму dir:

ls -dlF --color * .* | head -n2 && ls -AlF | LC_ALL=C grep "^d" | 
LC_ALL=C sort -k 9df && ls -AlF | LC_ALL=C grep "^[l-]" | 
LC_ALL=C sort -k 9df && echo -e `find -maxdepth 1 -type d ! -name . | 
wc -l` Dir\(s\) `du -hs | cut -f 1`\\t\\t`find -maxdepth 1 -type f | 
wc -l` File\(s\) `find -maxdepth 1 -type f -print0 | du -ch --files0-from=- | 
tail -n 1 | cut -f 1`\\t\\t`find -maxdepth 1 -type l | wc -l` Link\(s\)

Чтобы упростить управление, я придумал отдельные команды для вывода каждого сегмента списка каталогов по своему вкусу, а затем собрал их вместе с помощью &&оператора.

  • ls -dlF --color * .* | head -n2- Извлечь ./и ../. Мы не хотим передавать их, sortпотому что они уже находятся в правильном порядке, и сортировка может привести к ../тому, что они будут перечислены первыми. -dВариант , чтобы избавиться от «полной» линии; Я хотел бы добавить, -Fчтобы показать косую черту для каталогов (он также помечает символические ссылки с "@", когда вы делаете простой ls -F).

  • ls -AlF | LC_ALL=C grep "^d" | LC_ALL=C sort -k 9df- Извлеките каталоги и отсортируйте их по имени файла (9-й столбец), игнорируя как символы без букв / пробелов ( dопция), так и регистр символов ( fопция). В ls -Aопции исключает ./и ../из списка , так как мы уже извлеченных их на предыдущем шаге. Я склонен ставить перед всеми grepи sortкомандами префикс LC_ALL=Cсброса локали, чтобы (1) вывод был согласованным для всех оболочек Unix, и (2) иногда вы могли видеть более высокую производительность, так как для него больше не было накладных расходов для тяжелого символа UTF-8, установленного на иметь дело с.

  • ls -AlF | LC_ALL=C grep "^[l-]" | LC_ALL=C sort -k 9df - Это похоже на шаг выше, но на этот раз мы сортируем файлы и символические ссылки.

  • find -maxdepth 1 -type d ! -name . | wc -l- Получить количество каталогов, исключая ./и ../.

  • find -maxdepth 1 -type f | wc -l - Получить количество файлов.

  • find -maxdepth 1 -type l | wc -l - Получить количество символических ссылок.

  • du -hs | cut -f 1 - Извлечение общего размера всех подкаталогов в удобочитаемом формате.

  • find -maxdepth 1 -type f -print0 | du -ch --files0-from=- | tail -n 1 | cut -f 1 - Извлечь общий размер всех файлов в удобочитаемом формате.

Давайте посмотрим наш новый dirпсевдоним в действии!

ДО:

$ ls -alF
total 22
drwxr-xr-x   13 Tom      Administ     4096 Oct 25 02:38 ./
drwxr-xr-x    3 Tom      Administ        0 Dec 24  2014 ../
drwxr-xr-x   15 Tom      Administ     4096 Sep 17 01:23 .VirtualBox/
-rw-r--r--    1 Tom      Administ      615 Oct 25 02:38 .aliases
-rw-r--r--    1 Tom      Administ    12742 Oct 24 11:47 .bash_history
-rw-r--r--    1 Tom      Administ     3234 Oct 24 15:06 .bash_profile
drwxr-xr-x    1 Tom      Administ        0 Jan 24  2015 .gem/
-rw-r--r--    1 Tom      Administ      586 Oct 24 03:53 .gitconfig
drwxr-xr-x    1 Tom      Administ     4096 Dec 28  2014 .ssh/
drwxr-xr-x    4 Tom      Administ        0 Jan 24  2015 .travis/
-rw-r--r--    1 Tom      Administ     6645 Oct 25 02:38 _viminfo
-rw-r--r--    1 Tom      Administ     4907 Oct 24 15:16 profile
drwxr-xr-x    1 Tom      Administ        0 Oct 24 22:20 tmp/

ПОСЛЕ:

$ dir
drwxr-xr-x   13 Tom      Administ     4096 Oct 25 02:38 ./
drwxr-xr-x    3 Tom      Administ        0 Dec 24  2014 ../
drwxr-xr-x    1 Tom      Administ        0 Jan 24  2015 .gem/
drwxr-xr-x    1 Tom      Administ     4096 Dec 28  2014 .ssh/
drwxr-xr-x    1 Tom      Administ        0 Oct 24 22:20 tmp/
drwxr-xr-x    4 Tom      Administ        0 Jan 24  2015 .travis/
drwxr-xr-x   15 Tom      Administ     4096 Sep 17 01:23 .VirtualBox/
-rw-r--r--    1 Tom      Administ      615 Oct 25 02:38 .aliases
-rw-r--r--    1 Tom      Administ    12742 Oct 24 11:47 .bash_history
-rw-r--r--    1 Tom      Administ     3234 Oct 24 15:06 .bash_profile
-rw-r--r--    1 Tom      Administ      586 Oct 24 03:53 .gitconfig
-rw-r--r--    1 Tom      Administ     4907 Oct 24 15:16 profile
-rw-r--r--    1 Tom      Administ     6645 Oct 25 02:38 _viminfo
      5 Dir(s) 2.8M           6 File(s) 31K           0 Link(s)

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


ОБНОВИТЬ

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

ls -AFoqv --color --group-directories-first | tail -n +2 && find -maxdepth 1 -type f -printf '%s\n' | awk '{total+=$1} END {print total" bytes"}'

Образец вывода:

$ dir
drwxr-xr-x 1 Tom     0 Mar 29 13:49 .aws/
drwxr-xr-x 1 Tom     0 Mar 29 13:49 .gem/
drwxr-xr-x 1 Tom     0 Mar 29 19:32 .ssh/
drwxr-xr-x 1 Tom     0 Mar 29 13:49 .zbstudio/
drwxr-xr-x 1 Tom     0 Jun 16  2016 temp/
drwxr-xr-x 1 Tom     0 Jul 13  2016 vimfiles/
-rw-r--r-- 2 Tom   365 Mar 30 10:37 .aliases
-rw-r--r-- 1 Tom 16028 Mar 30 12:12 .bash_history
-rw-r--r-- 2 Tom  2807 Mar 30 12:12 .bash_profile
-rw-r--r-- 2 Tom  2177 Mar 29 23:24 .functions
-rw-r--r-- 1 Tom  1091 Mar 30 10:34 .gitconfig
-rw-r--r-- 1 Tom  8907 Mar 29 14:45 _viminfo
-rw-r--r-- 1 Tom  2444 Jul 13  2016 _vimrc
33819 bytes

Поскольку новая версия Git Bash для Windows поддерживает --group-directories-first, нам больше не нужно возвращаться sort. Несмотря на то, что новый псевдоним не отображает столько информации, сколько предыдущий псевдоним, выигрыш в производительности более чем оправдан. Как привилегия, вы также получаете цвета!

thdoan
источник
Отличный ответ! Но когда вы говорите: «После долгих взломов я наконец-то придумал однострочник…». Да, действительно, в классическом смысле это не «однострочник». Возможно, имеет смысл взять эту логику и сделать ее автономным сценарием оболочки и просто запустить ее или назвать ее псевдонимом.
JakeGould
@JakeGould Ты быстр! Я даже еще не закончил корректуру своего ответа, а вы уже закончили читать его и отстрелили комментарий :). Да, это главный кандидат на функцию, но в то время я был слишком ленив, поэтому просто бросил ее в мой файл .bash_aliases. С другой стороны, я обычно пишу функцию только тогда, когда я не могу что-то сделать без передачи параметров.
thdoan
@ 10basetom: Быстрый вопрос: Как получить разные цвета для столбцов в ls? Я могу раскрасить имена файлов по типу файла , используя ls --color, но я не вижу способа получить эти полезные цвета для столбцов. В чем секрет?
Пиркс,
@Pirx Полагаю, столбцы окрашены подсветкой синтаксиса Stack Exchange по умолчанию :-).
августа
Да, это похоже на случай, но это отличная идея, и решения в этом есть ;-)
Pirx
6

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

Вы можете просто попробовать:

ls -al | сортировать -k1 -r

или это, чтобы сохранить алфавитный порядок для файлов с такими же разрешениями:

ls -al | сортировать -k1,1 -k9,9 -r

или, как сказал одиннадцать81 (но эта версия перечисляет все):

ls -la | grep "^ d" && ls -la | grep "^ -" && ls -al | grep -v "^ [d | -]"

Studer
источник
1
Это более хорошее решение IMO. Использование нескольких процессов и каналов для сортировки вместо конвейерной сортировки кажется отсталым. Тем более что ls- al|sort -k1 -rработает. Чего не хватало, так это только -rфлага.
Брайс
@brice Вещь , которая беспокоит меня о « своего рода» является то , что ./и ../не будет первые две строки, в этом порядке. Кроме того, я согласен, что это более эффективное решение.
thdoan
Как покрасить вывод?
Даниэль
5

К ответу delerious010 я бы добавил, что если вы хотите упорядочить в старом стиле:

LANG=C ls -la --group-directories-first

(или используйте LC_ALL или LANGUAGE или LC_COLLATE, установленный в «C»).

Это даст что-то похожее на:

.
..
DIR
Dir
dir
.hidden
123
UC_FILE
Uc_file
lc_file

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

Деннис Уильямсон
источник
2

Вот функция, которая делает это (bash или zsh): И ... Я не предполагаю, что это лучший способ, но это тот, который я придумал и использую прямо сейчас:

функция LSS
{
    # Показывает список каталогов с каталогами вверху.

    команда ls --color = всегда $ @ | egrep '^ d | total'
    команда ls --color = всегда $ @ | egrep -v '^ d | total';
}
супермагическим
источник
Просто к вашему сведению это не работает. Вам необходимо использовать формат длинного списка ( ls -l), чтобы выполнить фильтрацию по типу файла. Также эта команда будет разбиваться на пробелы (в bash). Вы должны процитировать примерно так: "$@"если вы хотите использовать этот подход, вы можете сделать что-то вроде этого:function lss {local temp="$(command ls -l --color=always "$@")"; egrep --color=never '^d|total' <<<"$temp"; egrep --color=never -v '^d|total' <<<"$temp"}
Six
2

ls -laX сначала покажет вам каталоги в алфавитном порядке, но накрутит список файлов.

Длинные варианты:

ls
    -l    # List
    --all
    -X    # Sort alphabetically by entry extension
Бобби
источник
Это будет работать, только если вы будете абсолютно уверены, что в каждом каталоге нет точек в имени.
одиннадцать81
1

По-другому ...

find . -d 1 -type d | ls -la | sort -r 

ИЛИ ЖЕ

ls -la | sort -r

ИЛИ ЖЕ

d=`find . -type d -d 1`;f=`find . -type f -d 1`; echo -e -DIRS- "\n$d\n" -FILES- "\n$f"
Эдди Б
источник
Что они делают? Где ты научился их печатать?
Тамара Вийсман
Ну, моя любимая ОС - Debian Linux. Ядро Debian gnu использует пакетную версию ls, которая поддерживает опцию --show-directoryies-first ... когда я начал использовать OSX, я просто взял все мои файлы bash dot из коробки Debian и сбросил их в свой домашний каталог ... I у меня было много bash_aliases, которые сломались так ... Именно тогда я должен был найти некоторые обходные пути для моих псевдонимов ...
Eddie B
Первый из них немного избыточен ... Нет смысла сортировать каталоги, так как это порядок, который мы должны изменять, а не каталоги ... 'ls -la | sort -r - это то, что действительно работает. В основном это заявляет ... 1) А) Найти. -d 1 -type d (Начать с этого каталога, выполнить поиск по одной глубине каталога и выполнить поиск только по каталогам) B) ls -la (перечислить файлы со всеми атрибутами) C) Сортировать их в обратном порядке 2) Выполнить как 1) просто отбросить поиск. ... это не нужно ... Мне больше нравится решение Studers ... :-)
Eddie B
1

TL; DR

alias ls='ls -lhF --color'

list_sorted() {
    ls $* | grep "^d";
    ls $* | grep "^-";
    ls $* | grep -v -E "^d|^-|^total"
}

alias ll=list_sorted

объяснение

Я использую комбинацию решений, представленных в ответах и ​​комментариях здесь.

По умолчанию ls

Прежде всего, я перезаписываю поведение по умолчанию для ls:

  • -l: Всегда отображать список как одномерный вертикальный список
  • -h: Отображать размеры файлов удобочитаемым способом (например, 4,0 КБ вместо 4096)
  • -F: Отображать индикаторы как косую черту для каталогов
alias ls='ls -lhF --color'

расширенный ll

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

Кроме того, каждый вызов lsпередается в grepкоманду. Здесь происходит сортировка. ls -l | grep "^d"например, только списки каталогов. Если каталоги должны быть перечислены первыми, это также должно стоять на первом месте в функции. Следующая вещь - файлы.

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

list_sorted() {
    # List directories
    ls $* | grep "^d";
    # List regular files
    ls $* | grep "^-";
    # List everything else (e.g. symbolic links)
    ls $* | grep -v -E "^d|^-|^total"
}

Наконец, я псевдоним функции для новой команды. В частности, я не хочу перезаписывать lsв случае нарушения моей функции в некоторых сценариях. Тогда я хочу иметь возможность использовать ls. Кроме того, вы всегда можете вызвать необъявленную lsкоманду, вызвав \ls.

alias ll=list_sorted

Примечания

  • Я использую ;вместо &&в качестве разделителя для команд. В противном случае невозможно отобразить содержимое каталогов, не содержащих каталогов (первая команда ls оценивается как false, что не позволяет выполнить следующую команду, поскольку она связана с &&. ;Избегает этого.)
kleinfreund
источник
0

Это решение сценария. Перечисляет только имена, без данных inode, в алфавитном порядке, без учета регистра, отформатированный в столбцы. Хотя это главная строка вместо основной колонки, как по умолчанию вывод ls. Столбцы становятся немного беспорядочными, если есть имя файла с> 26 символами.

rm -f /tmp/lsout
ls -1p | grep / | sort -f >> /tmp/lsout
ls -1p | grep -v / | sort -f >> /tmp/lsout

IFS=$'\n' read -d '' -r -a lines < /tmp/lsout

printf "%-24s  %-24s  %-24s\n" "${lines[@]}"

И еще, с дополнительным форматированием.

rm -f /tmp/lsout
echo "  ---- Directories ---- " >> /tmp/lsout
ls -1p | grep / | sort -f >> /tmp/lsout
IFS=$'\n' read -d '' -r -a lines < /tmp/lsout
printf "%-24s  %-24s  %-24s\n" "${lines[@]}"

rm -f /tmp/lsout
echo "  ------- Files ------- " >> /tmp/lsout
ls -1p | grep -v / | sort -f >> /tmp/lsout
IFS=$'\n' read -d '' -r -a lines < /tmp/lsout
printf "%-24s  %-24s  %-24s\n" "${lines[@]}"

Вывод для последнего выглядит следующим образом, за исключением цветов:

  ---- Directories ----   archive/                  bookmarks/              
Desktop/                  Documents/                Downloads/              
fff/                      health/                   Library/                
Movies/                   Music/                    Pictures/               
Public/                   rrf/                      scifi/            
testdir/                  testdir2/                                         
  ------- Files -------   @todo                     comedy            
delme                     lll                       maxims                  
schedule                  vtokens style

Просто помните, чтобы не использовать псевдоним или изменить поведение по умолчанию ls, так как этот скрипт вызывает его.

Igorio
источник