在Unix中使用“ ls”时,如何对第一个目录然后对文件等进行排序


91

我想使用该ls命令先显示目录,然后显示文件。我试过了:

ls -la | sort -k 1

但是我的订单错了。


这是因为使用-前先d出现了sort
Nifle

4
旧时的unix头(GUI以前的头)用于大写其文件夹名,而使普通文件名不大写,以自动获得该结果。
JRobert

有用的问题!也许是时候将接受的答案更改为更简单且不会破坏端子颜色的答案了吗?
ippi

试试ls -lh --group-directories-first
Diogo

Answers:


28

以下命令将首先列出目录,然后列出普通文件,然后列出链接。

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

同样,为该命令创建别名以保存击键也很有意义。

编辑:

如果先要目录,然后再要不是目录的所有内容,请使用以下命令:

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


1
如果文件夹中有套接字或FIFO,则此命令不会列出所有内容
Studer 2010年

1
该编辑版本仍应与其他类型一起使用。第一个grep说所有以“ d”开头的内容,第二个说所有不以“ d”开头的内容。当然,一切都以广告开头还是不以广告开头,对吧?
Ry4an Brase 2012年

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 2015年

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选择,但是最短的imo是ls -la|sort
Steven Pribilinskiy

204

我非常喜欢* nix,也喜欢看到其中一些回复所具有的创造力...

我的在GNU Linux上并不那么喜欢:

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

鉴于我对linux CLI应用程序更加满意,因此我也倾向于在OSX上更新coreutils:

brew install coreutils
alias ls='/usr/local/bin/gls --color -h --group-directories-first'

6
不幸的是,这在osx终端上不起作用,因为-选项不可用。
MEM 2012年

7
重新爱:这是讽刺吗?如果是这样,我会同意。
allyourcode

4
别名ls的目的是定义90%的时间要使用的配置元素。减少击键次数以达到所需的输出。如果您希望拥有本机ls输出,则可以始终使用/ bin / ls。
jonathanserafini 2014年

4
@MEM如果您使用的是OS X,并且喜欢使用Terminal,那么应该可以使用brew install bash 它!:)
Andrew Ashbacher 2015年

5
我认为:这应该是公认的答案,因为它列出了命令行选项来完成准确的目标,而不是一个令人费解的设置的grep的等
瑞安格里格斯

17

对于Mac用户coreutils

brew install coreutils

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

假设您的系统已准备好进行自制程序


7
gls而是。对?
Paul Irish

1
是的,默认情况下。您还可以默认将coreutils与一起使用PATH="/usr/local/opt/coreutils/libexec/gnubin:$PATH"
benesch

7

我想在目录列表中看到某些内容,到目前为止,这里的答案都不能满足以下所有要求。我对目录清单的要求:

  1. 目录和文件按字母顺序排序
  2. 目录列在第一位
  3. 符号链接(符号链接)的排序方式类似于文件
  4. 排序不区分大小写
  5. 排序会忽略文件名中的所有前导非字母字符
  6. 清单包括目录的总数(不包括./../),文件和链接
  7. 清单包括目录和文件的总大小(磁盘使用情况)
  8. 清单在Linux和Windows(Git Bash shell)上必须看起来相同-这是最难弄清的,因为诸如--group-directories-firstWindows的Git Bash中不方便的便捷选项

经过大量的修改后,我终于想到了我满意的单线(尽管行很长;-)。我已将其分配给名为“ 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选项从列表中排除./../,因为我们已经在上一步中将它们提取出来了。我倾向于在所有命令grepsort命令之前加上LC_ALL=C语言环境重置,以使(1)输出在Unix shell之间保持一致,并且(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

由于新版本的Windows Git Bash支持--group-directories-first,因此我们不再需要依靠sort。即使新别名显示的信息不如以前的别名多,但性能提升还是值得的。作为一种振作,您还可以获得颜色!


好答案!但是当您说:“经过多番研究之后,我终于想出了一种单面纸……”是的,实际上,这并不是经典意义上的“单面纸”。采取这种逻辑并使其成为独立的Shell脚本,然后运行它或将其作为别名可能是有意义的。
JakeGould 2015年

@JakeGould你很快!我什至还没有完成我的答案的校对,而您已经完成阅读并提出评论了:)。是的,它是函数的主要候选对象,但是当时我太懒了,因此只需将其放入我的.bash_aliases文件即可。另一方面,我通常只在无法传递参数的情况下编写函数。
thdoan

@ 10basetom:快速问题:如何获得ls中列的不同颜色?我可以使用ls --color按文件类型为文件名着色,但是我没有找到一种为这些列获取有用颜色的方法。有什么秘密?
Pirx

@Pirx我相信这些列是用默认的Stack Exchange语法突出显示颜色的:-)。
thdoan

是的,这似乎是事实,但这是个好主意,解决方案在;-)
Pirx

6

您有几种选择,取决于您是否要保持字母顺序。

您可以尝试:

ls -al | 排序-k1 -r

或这样,以保持具有相同权限的文件的字母顺序:

ls -al | 排序-k1,1 -k9,9 -r

或者,如eleven81所说(但此版本列出了所有内容):

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


1
这是IMO更好的解决方案。使用多个流程和管道进行排序而不是通过管道进行排序似乎有些倒退。特别是因为ls- al|sort -k1 -r工作。所缺少的只是-r国旗。
布莱斯

@brice困扰我关于“排序”是,事情./../不会是第一个两行的顺序。除此之外,我同意这是更有效的解决方案。
thdoan

如何为输出着色?
Danijel

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 = always $ @ | egrep'^ d |总计'
    命令ls --color = always $ @ | egrep -v'^ d | total';
}

只是fyi,这似乎不起作用。您需要使用长列表格式(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"}
2015年

2

ls -laX 会先按字母顺序显示目录,但会损坏文件列表。

长选项:

ls
    -l    # List
    --all
    -X    # Sort alphabetically by entry extension

仅当您可以完全确定每个目录的名称中都没有点时,这才起作用。
eleven81 2010年

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"

这些是做什么的?您在哪里学习打字?
Tamara Wijsman 2012年

好吧,我首选的操作系统是Debian Linux。Debian的ls的gnu核心utils软件包版本支持--show-directories-first选项...当我开始使用OSX时,我只是从Debian盒子中抓取了我所有的bash点文件,并将它们放在了我的主目录中...我有很多bash_aliases崩溃了……于是我不得不找出一些别名的解决方法……
Eddie B

第一个有点多余...实际上没有理由对目录进行排序,因为这是我们需要修改而不是目录的顺序...'ls -la | sort -r'才是真正有效的方法。基本上是说... 1)A)查找。-d 1型d(从此目录开始,搜索一个目录深度并仅搜索目录)B)ls -la(列出所有属性的文件)C)对它们进行反向排序2)做为1)只需删除find即可。 ..不需要...我实际上更喜欢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.0K而不是4096)
  • -F:显示指示符,例如目录的结尾斜杠
alias ls='ls -lhF --color'

扩展的 ll

接下来,我编写一个包含排序逻辑的函数。对于每个ls参数,我都会传递任何原始传递的参数。这样一来,我可以使用与要列出的工作目录不同的工作目录中的别名ls -a ~

同样,对的每个调用ls都通过管道传递给grep命令。在这里,进行排序。ls -l | grep "^d"例如仅列出目录。如果应该首先列出目录,则该函数也必须放在第一位。接下来是文件。

最后,我显示了既不是目录又不是文件的所有内容(也没有显示目录内容总大小的行)。这是通过以下方式完成的:grepping Directoy,常规文件条目和总条目,然后通过-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,因此不允许执行下一个命令,因为它与&&。结合使用;避免了这种情况。)

0

这是一个脚本解决方案。仅列出名称,没有索引节点数据,按字母顺序,不区分大小写,格式化为列。尽管它像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的默认行为,因为此脚本会对其进行调用。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.