Linux命令以树的形式打印目录结构

是否有任何linux命令,我可以从Bash脚本调用,将以树的形式打印目录结构,例如,

folder1
a.txt
b.txt
folder2
folder3
560742 次浏览

你可以用这个:

ls -R | grep ":$" | sed -e 's/:$//' -e 's/[^-][^\/]*\//--/g' -e 's/^/   /' -e 's/-/|/'

它将显示当前子目录的图形化表示,没有文件几秒钟后,例如在/var/cache/:

   .
|-apache2
|---mod_cache_disk
|-apparmor
|-apt
|---archives
|-----partial
|-apt-xapian-index
|---index.1
|-dbconfig-common
|---backups
|-debconf

Source .

这是你要找的吗?它应该在大多数发行版中(可能作为可选安装)。

~> tree -d /proc/self/
/proc/self/
|-- attr
|-- cwd -> /proc
|-- fd
|   `-- 3 -> /proc/15589/fd
|-- fdinfo
|-- net
|   |-- dev_snmp6
|   |-- netfilter
|   |-- rpc
|   |   |-- auth.rpcsec.context
|   |   |-- auth.rpcsec.init
|   |   |-- auth.unix.gid
|   |   |-- auth.unix.ip
|   |   |-- nfs4.idtoname
|   |   |-- nfs4.nametoid
|   |   |-- nfsd.export
|   |   `-- nfsd.fh
|   `-- stat
|-- root -> /
`-- task
`-- 15589
|-- attr
|-- cwd -> /proc
|-- fd
| `-- 3 -> /proc/15589/task/15589/fd
|-- fdinfo
`-- root -> /


27 directories

样本取自维护者的网页。

您可以添加选项-L #,其中#被一个数字替换,以指定最大递归深度。

删除-d以显示also文件。

将Hassou的解决方案添加到你的.bashrc,尝试:

alias lst='ls -R | grep ":$" | sed -e '"'"'s/:$//'"'"' -e '"'"'s/[^-][^\/]*\//--/g'"'"' -e '"'"'s/^/   /'"'"' -e '"'"'s/-/|/'"'"

我正在美化@Hassou的答案的输出:

ls -R | grep ":$" | sed -e 's/:$//' -e 's/[^-][^\/]*\//──/g' -e 's/─/├/' -e '$s/├/└/'

这很像tree的输出:

.
├─pkcs11
├─pki
├───ca-trust
├─────extracted
├───────java
├───────openssl
├───────pem
├─────source
├───────anchors
├─profile.d
└─ssh

你也可以为它创建一个别名:

alias ltree=$'ls -R | grep ":$" | sed -e \'s/:$//\' -e \'s/[^-][^\/]*\//──/g\' -e \'s/─/├/\' -e \'$s/├/└/\''

顺便说一下,tree在一些环境中是不可用的,比如MinGW。所以备选方案是有用的。

还可以使用find和awk命令的组合来打印目录树。详情请参考“如何使用linux查找和awk组合命令打印多层树目录结构

find . -type d | awk -F'/' '{
depth=3;
offset=2;
str="|  ";
path="";
if(NF >= 2 && NF < depth + offset) {
while(offset < NF) {
path = path "|  ";
offset ++;
}
print path "|-- "$NF;
}}'

该命令适用于显示文件夹和文件

find . | sed -e "s/[^-][^\/]*\// |/g" -e "s/|\([^ ]\)/|-\1/"

示例输出:

.
|-trace.pcap
|-parent
| |-chdir1
| | |-file1.txt
| |-chdir2
| | |-file2.txt
| | |-file3.sh
|-tmp
| |-json-c-0.11-4.el7_0.x86_64.rpm

@javasheriff 在这里的评论它被淹没在评论中,并将其作为答案发布,可以帮助用户轻松发现它。

在bashrc中添加下面的函数可以让您在不带任何参数的情况下运行该命令,该命令显示当前目录结构,当以任何路径作为参数运行时,将显示该路径的目录结构。这样可以避免在运行命令之前切换到特定目录。

function tree() {
find ${1:-.} | sed -e "s/[^-][^\/]*\//  |/g" -e "s/|\([^ ]\)/|-\1/"
}

这在gitbash中也适用。

来源:@javasheriff 在这里的评论

由于我对其他(非tree)答案的输出不太满意(见我对哈苏的回答的评论),我尝试模拟trees输出多一点。

这与罗伯特的答案相似,但水平线并不都是从起点开始的,而是从应该开始的地方开始的。虽然不得不使用perl,但在我的情况下,在我没有tree的系统上,perl是可用的。

ls -aR | grep ":$" | perl -pe 's/:$//;s/[^-][^\/]*\//    /g;s/^    (\S)/└── \1/;s/(^    |    (?= ))/│   /g;s/    (\S)/└── \1/'

输出(缩短):

.
└── fd
└── net
│   └── dev_snmp6
│   └── nfsfs
│   └── rpc
│   │   └── auth.unix.ip
│   └── stat
│   └── vlan
└── ns
└── task
│   └── 1310
│   │   └── net
│   │   │   └── dev_snmp6
│   │   │   └── rpc
│   │   │   │   └── auth.unix.gid
│   │   │   │   └── auth.unix.ip
│   │   │   └── stat
│   │   │   └── vlan
│   │   └── ns

欢迎提出建议,避免多余的竖线:-)

我仍然非常喜欢Hassou回答的评论中的本的解决方案,没有(不完全正确的)行,它更干净。对于我的用例,我另外删除了全局缩进,并添加了ls隐藏文件的选项,如下所示:

ls -aR | grep ":$" | sed -e 's/:$//' -e 's/[^-][^\/]*\//  /g'

输出(更缩短):

.
fd
net
dev_snmp6
nfsfs
rpc
auth.unix.ip
stat
vlan
ns

由于它是一个成功的评论,我添加它作为一个答案:
要以树的形式打印目录结构,
文件< / >强

 find . | sed -e "s/[^-][^\/]*\//  |/g" -e "s/|\([^ ]\)/|-\1/"

最好的答案当然是树。但是,为了改进依赖于grepping ls -R输出的其他答案,这里有一个shell脚本,它使用awk打印子目录树。首先,一个输出的例子:

.
└── matching
├── bib
├── data
│   └── source
│       └── html
├── data
│   └── plots
├── method
│   ├── info
│   └── soft
│       ├── imgs
│       │   ├── ascii
│       │   └── symbol
│       └── js
└── ms

然后,代码:

ls -qLR 2>/dev/null \
| grep '^./' \
| sed -e 's,:$,,' \
| awk '
function tip(new) { stem = substr(stem, 1, length(stem) - 4) new }
{
path[NR] = $0
}
END {
elbow = "└── "; pipe = "│   "; tee = "├── "; blank = "    "
none = ""
#
# Model each stem on the previous one, going bottom up.
for (row = NR; row > 0; row--) {
#
# gsub: count (and clean) all slash-ending components; hence,
# reduce path to its last component.
growth = gsub(/[^/]+\//, "", path[row]) - slashes
if (growth == 0) {
tip(tee)
}
else if (growth > 0) {
if (stem) tip(pipe) # if...: stem is empty at first!
for (d = 1; d < growth; d++) stem = stem blank
stem = stem elbow
}
else {
tip(none)
below = substr(stem, length(stem) - 4, 4)
if (below == blank) tip(elbow); else tip(tee)
}
path[row] = stem path[row]
slashes += growth
}
root = "."; print root
for (row = 1; row <= NR; row++) print path[row]
}
'

代码给出了比其他解决方案更好看的结果,因为在子目录树中,任何分支中的装饰都依赖于它下面的分支。因此,我们需要以相反的顺序处理ls -R的输出,从最后一行到第一行。