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

folder1
   a.txt
   b.txt
folder2
   folder3

当前回答

最好的答案当然是树。但是,为了改进依赖于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的输出,从最后一行到第一行。

其他回答

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

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

这在gitbash中也适用。

来源:@javasheriff的评论

由于我对其他(非树)答案的输出不太满意(参见我在Hassou's answer的评论),我试着更多地模拟树的输出。

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

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

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

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

输出(更缩短):

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

将已有的答案组合并扩展为t壳函数

t() {
  find -E "${1:-.}" -maxdepth "${2:-3}" \
    -not -regex ".*\/((.idea|.git|.venv|node_modules|venv)\/.*|.DS_Store)" \
  | sort | sed \
    -e "s/[^-][^\/]*\// ├ /g" \
    -e "s/├ \//├ /g" \
    -e "s/├  ├/│  ├/g" \
    -e "s/├  ├/│  ├/g" \
    -e "s/├  │/│  │/g" \
    -e '$s/├/└/'
}

适用于Mac:

$ t
.
 ├ src
 │  ├ .idea
 │  ├ plugins
 │  │  ├ .flake8
 │  │  ├ .git
 │  │  ├ .github
 │  │  ├ .gitignore
 │  │  ├ .pre-commit-config.yaml
 │  │  ├ .python-version
 │  │  ├ Makefile
 │  │  ├ README.md
 │  │  ├ buildspecs
 │  │  ├ cicd
 │  │  ├ cicd.py
 │  │  ├ docker
 │  │  ├ packages
 │  │  ├ plugin_template
 │  │  ├ plugins
 │  │  ├ scripts
 │  │  └ venv


$ t . 2
.
 ├ src
 │  ├ .idea
 │  └ plugins


$ t src/plugins/ | more
 │  ├
 │  ├ .flake8
 │  ├ .git
 │  ├ .github
 │  │  ├ pull_request_template.md
 │  ├ .gitignore
 │  ├ .pre-commit-config.yaml
 │  ├ .python-version
 │  ├ Makefile
 │  ├ README.md
 │  ├ buildspecs
 │  │  ├ test-and-deploy.yml
 │  ├ cicd
:

|更可以放在函数的末尾,方便使用。

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

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

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

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