我希望以这样的方式操作 $tree --noreport$ 的输出,即用匹配数量的空格替换每行上的前导框绘制字符和空格。如果我要编写匹配这些字符的模式,那就是^\\(\u2500\\|\u2514\\|\u251C\\| \\)*\u2500
.该字符串将被包裹起来,$'...'
因为 sed 无法识别 Unicode 转义序列。此模式出现在tree --noreport
除第一行之外的输出的每一行上。每个匹配字符串中的每个字符都需要替换为空格。
输入示例:
.
├── docs
│ ├── jokes
│ │ └── knock_knock.txt
│ └── work
├── images
└── .profile
输出示例:
.
docs
jokes
knock_knock.txt
work
images
.profile
我现在意识到,出于我的目的,我需要消除文件或文件夹名称开始位置的歧义(文件或文件夹名称可能以一个或多个空格开头),因此输出实际上应该类似于:
.
/docs
/jokes/
/knock_knock.txt
/work
/images
/.profile
我提供的模式的末尾\u2500
实际上区分了树的格式和文件/文件夹名称的开头。
答案1
您可以在循环中一次替换一个,如下所示:
tree --noreport | sed $'
:1
s/^\\( *\\)\\([\ua0\u2500\u2502\u2514\u251C]\\)\\([\ua0\u2500\u2502\u2514\u251C ]*\u2500 \\)/\\1 \\3/
t1
s|\u2500 | /|'
(您至少错过了\ua0
(不间断空格)和\u2502
(也在您的示例中显示),它们至少│
出现在我的版本的输出中)。tree
如果有些文件的名称"─ "
前面可能包含其中一些字符,那就被愚弄了。
另一种方法(假设您确实想要插入/
且您调用的目录tree
不包含):在第一次出现 后"─ "
插入,然后在循环中用空格替换第一个之前的每个字符。/
"\u2500 "
/
tree --noreport | sed '
s|'$'\u2500'' |&/|;t1
b
:1
s|^\( *\)[^ /]|\1 |
t1'
使用以下命令会更容易一些perl
:
tree --noreport | perl -C -pe 's{^.*?\x{2500} }{" " x length($&) . "/"}e'
答案2
这是一个bash
递归输出在顶级目录中找到的名称的函数:
mytree () (
topdir="${1-.}"
indent="${2-0}"
shopt -s nullglob
shopt -s dotglob
# output directory name
printf "%${indent}s'%s'/\n" "" "${topdir##*/}"
indent=$(( indent + 4 ))
for name in "$topdir"/*; do
if [ -h "$name" ]; then
# output symbolic link name and target
printf "%${indent}s'%s' --> '%s'\n" "" "${name##*/}" "$( readlink -- "$name" )"
elif [ -d "$name" ]; then
# recurse into directories
mytree "$name" "$indent"
else
# output other type of name (not directory or symbolic link)
printf "%${indent}s'%s'\n" "" "${name##*/}"
fi
done
)
该函数mytree
采用一个参数(第二个参数仅在递归调用中使用),这是要处理的顶级目录。如果没有给出参数,它将使用当前目录作为列出的顶级目录。
输出如下:
'Work'/
'Data'/
's3wes.all.tab.frq.counts'
's3wes.con.tab.frq.counts'
'sullivan.txt'
'Development'/
'ENA-submission'/
'.git'/
'COMMIT_EDITMSG'
ETC。
也就是说,名称用单引号引起来,并且目录将有一个尾随/
.此外,符号链接将显示为,例如,
'embl-validator.jar' --> 'embl-api-validator-1.1.158.jar'
通过更改三个调用可以轻松更改输出格式printf
。