Bash:没有文件夹分组的ls *


12

如果我输入:

ls source/*

source/fonts:
fontello

source/images:
bg1.png                eng.png        fra.png   

我得到了文件列表,按文件夹名称分组。我怎样才能简单地获取文件名列表?

ls source/*

source/fonts/fontello
source/images/bg1.png
source/images/eng.png
source/images/fra.png   

谢谢


如果这是用于脚本编写,您可能希望查看mywiki.wooledge.org/ParsingLs。(也就是说,也有一些方法可以使用find错误;特别是,如果你正在运行for file in $(find ...),你已经击中了其中一​​个)。
查尔斯达菲2015年

Answers:


13

没有输出更改似乎不可能,但这是一个简单的替代方法:

find source/ -type f

或者(特定于GNU查找),仅在您问题的深度获取文件:

find source/ -type f -mindepth 2 -maxdepth 2

(或者如果你想要的目录ls给你,删除-type f


5

如果添加一些psychedlics(ls -d),你可以简单地坚持ls :

# mkdir test
# cd test
# mkdir A B C
# touch {A,B,C}/file*
# ls -d */*    
A/file  B/file  C/file

@Cthulhu ok我的例子太短,如果你有A,B a / o C中的文件夹-d有助于只显示你选择的内容。我实际上不喜欢找到你可以用ls -d定义深度
ikrabbe 2015年

我建议编辑另一个答案以限制深度。
o11c 2015年

@ o11c非常好,但仍然find是一个胖胖的野兽。
ikrabbe 2015年

3

你可能对“穷人”感兴趣find

shopt -s globstar

shopt -s 找到命名的shell选项。该globstar选项在bash(1)中定义如下:

如果设置,则**文件名/路径名扩展上下文中使用的模式将匹配文件[sic]和零个或多个目录和子目录。如果模式后跟a /,则只有目录和子目录匹配。

所以,完成后shopt -s globstar,请执行以下任何命令:

ls -d1  -  source / **                  #'d'后面的字符是数字1。
ls -d  -  source / ** | cat             #ie,它会将其写入管道中的任何命令。
printf“%s \ n”来源/ **

将产生输出:

source/
source/fonts
source/fonts/fontello
source/images
source/images/bg1.png
source/images/eng.png
source/images/fra.png

不幸的是,这也包括目录名称。它可以帮助你有点知道

printf "%s\n" source/**/

将产生输出:

source/
source/fonts
source/images

即,只有目录名称。你可能在第一组命令之一的输出重定向到一个文件,重定向上述的第二文件的输出,然后用commdiff或类似的东西,减去从第一个第二个文件,只留下普通文件(非目录)。但是不要这样做。

另一种方法(这不是好)是

ls -d --file-type -- source/** | grep -v '/$'

--file-type选项告诉ls显示/ 每个目录名称的末尾(以及其他(特殊)文件类型末尾的其他字符),如下所示:

来源//                             #添加了一个额外的 
源/字体/                        #添加了一个
源极/字体/ fontello
source / images /                       #添加一个
源极/图像/ bg1.png
源极/图像/ eng.png
源极/图像/ fra.png

然后grep -v '/$'删除以...结尾的行/; 即目录名称。不幸的是,POSIX--file-type没有指定该选项。如果您的版本ls不支持,请使用-F。这就像--file-type 它除了它还显示*在可执行文件的名称的末尾,有些人觉得烦人。你可以用sed以下方法消除它们

ls -dF -- source/** | sed -e '/\/$/d' -e 's/\*$//'

如果你想对所有文件(只有文件)做一些事情,你可以这样做

for f in source / **
做
    如果[-f“$ f”]
    然后
        在此处插入要应用于纯文件的命令。
    科幻
DONE

笔记:

  • ls输出到终端,并且它不在-ll ong)模式时,它每行写入多个名称(除非名称很长)。您可以通过指定-1(一个)或通过将输出重定向到文件或管道来强制它为每行写一个名称。
  • 你可能并不真正需要--ls命令,因为你列出一个目录,其内容创建。您应该*在未知目录中列出时使用它,以防止以文件名开头-
  • 不要尝试解析输出ls
  • globstar外壳选项出现不被POSIX定义。(事实上​​,我不确定POSIX是否识别任何 shell选项。)虽然它似乎是一个bash主义,但要注意 - 它可能不会出现在所有版本的bash中。
  • 如果fontsimages具有子目录,**将以递归方式将它们全部列出。一种(有点kludgy和不可靠)限制深度的方法是

    ls -d --file-type -- source/** | grep -v '\(/.*\)\{3\}'
    

    删除包含三个或更多/字符的行。

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.