我需要列出某个路径的子目录。分隔应该用空格而不是换行。
我也不想要子目录的绝对路径,只想要它们的名称。
# correct
dir1 dir2 dir3
# incorrect: separation with new lines
dir1
dir2
dir3
# incorrect: absolute paths
/home/x/y/dir1 /home/x/y/dir2 /home/x/y/dir3
Run Code Online (Sandbox Code Playgroud)
我看过很多其他帖子,比如这个帖子,但他们没有完成我的要求。
我已经尝试过ls -d ~/y,但它列出了绝对路径并用新行分隔。我想我可以使用 sed 删除路径中不相关的部分,然后删除所有新行。但我无法让它工作,似乎应该有更好的解决方案
假设您正在使用 GNU 工具,您可以使用 GNUbasename来获取特定目录中所有子目录的名称。然后,您可以将paste其格式化为空格分隔的列表。
basename -a /some/path/*/ | paste -d ' ' -s -
Run Code Online (Sandbox Code Playgroud)
上面的命令利用了这样一个事实:GNUbasename有一个-a选项可以返回在其命令行上作为操作数给出的多个路径名的文件名部分。
我们使用以 结尾的文件匹配模式/来生成 GNU 的路径名basename。只有目录可以匹配这样的模式。
最后,paste从 GNU 生成的换行符分隔列表中创建空格分隔列表basename。
请注意,如果任何原始目录名称包含空格字符,则很难解析生成的文件名列表。
请注意,如果目录包含符号链接,此方法将尝试跟踪这些符号链接。
为了限制我们使用任何外部工具,我们可以在 shell 中使用数组bash来存储和操作目录路径。
shopt -s nullglob
topdir=/some/path
dirpaths=( "$topdir"/*/ )
dirpaths=( "${dirpaths[@]#$topdir/}" )
dirpaths=( "${dirpaths[@]%/}" )
printf '%s\n' "${dirpaths[*]}"
Run Code Online (Sandbox Code Playgroud)
上面的 shell 代码扩展了与我们在本答案的第一部分中使用的相同的通配模式,但将结果目录路径存储在数组中dirpaths。$topdir/然后,它从数组的每个元素和尾随中删除已知前缀,/然后将数组打印为空格分隔名称的单个字符串。最后一行的名称之间使用的分隔符将是 的第一个字符$IFS,默认情况下是空格。
使用find,您可以在您感兴趣的特定顶级目录中查找子目录,同时确保不返回顶级目录本身。您还将停止find进入子目录。
topdir=/some/path
find "${topdir%/}/." ! -name . -prune -type d -exec basename {} \; | paste -d ' ' -s -
Run Code Online (Sandbox Code Playgroud)
上面的命令使用否定测试来避免搜索起点-name,并且它会修剪搜索树-prune,以便find不会递归到任何子目录。我们调用basename每个找到的目录,将目录的文件名输出到单独的行上。作为最后一步,我们通过find管道传输结果,将paste输出格式化为单行上的空格分隔列表。
使用 GNU find,您可以将其写为
find /some/path -mindepth 1 -maxdepth 1 -type d -printf '%f\n' | paste -d ' ' -s -
Run Code Online (Sandbox Code Playgroud)
像这样使用find将列出具有隐藏名称的目录,并且您将看不到任何符号链接的目录。
在zshshell 中,您将能够使用更高级的 shell 通配模式来仅挑选目录的文件名并一次性打印它们。
print -r -- /some/path/*(/:t)
Run Code Online (Sandbox Code Playgroud)
此命令使用 glob 限定符 ,/:t由两部分组成,影响前面的通配模式/some/path/*。使/模式仅匹配目录(不是符号链接的目录;用于该用途-/),同时:t提取每个生成的路径名的“尾部”,即文件名部分。
该print -r命令使用空格作为分隔符来打印其参数,同时避免扩展数据中的转义序列(如\n或 ) 。\t使用--分隔选项中的操作数(也-适用于 shell 中的操作ksh)可确保 glob 扩展产生的目录名称不会被视为选项,即使它们以-.
您可以在bashshell 中使用它来生成列表。
zsh -c 'print -r -- /some/path/*(/:t)'
Run Code Online (Sandbox Code Playgroud)