在 Bash 中使用 ls 仅列出目录,但保留 ls 格式且没有 dirname
Listing only directories using ls in Bash but preserve ls format and without dirname
this similar question 已经有很多答案了。但是 none 满足我的要求。我要
列出一个目录下的所有目录,不用glob(*
)语法,即我想直接用lsdir somedir
输出应包含目录的基本名称,就像您使用 ls
时一样,例如:
$ lsdir path/to/some/dir
dir1 dir2 dir3 dir4
但不是这个:
$ lsdir path/to/dir
path/to/dir/dir1 path/to/dir/dir2 path/to/dir/dir3 path/to/dir/dir4
为了满足要求 1,定义一个函数似乎是可行的,但无论如何我们将使用 -d
选项,列出 ls
命令参数的目录本身。
并且在使用 -d
选项时,ls
列出目录名称并在其父目录前加上前缀,如上所示。
ls
格式(颜色、对齐、排序)应保留。
为了满足要求 2,我们可以使用 find
但这样我们就失去了所有 ls
输出格式,比如着色(基于自定义的 dircolors 主题)、对齐(输出对齐列)、排序(使用各种标志和列优先方式自定义排序),也许还有其他一些东西。
我知道同时想要这么多功能太贪心了,事实上我可以没有所有这些功能。
可以手动模拟 ls
输出格式,但这太不一致了。
我想知道是否有办法实现这一点并仍然利用 ls
,即如何使用 ls
.
实现要求 2
这可能是您要找的:
cd path/to/dir && dirs=(*/) && ls -d "${dirs[@]%?}"
或者,也许
(shopt -s nullglob; cd path/to/dir && dirs=(*/) && ((${#dirs[@]} > 0)) && ls -d "${dirs[@]%?}")
第二个版本在子 shell 中运行,如果 path/to/dir
.
中没有任何子目录,则不打印任何内容
基于@M。 Nejat Aydin 的出色回答,我将进一步改进使其成为一个有用的命令,尤其是在处理选项和多个目录方面。
list_directories() {
local opts=()
local args=()
for i in $(seq $#); do
if [[ "${!i}" == -* ]]; then
opts+=("${!i}")
else
args+=("${!i}")
fi
done
(( ${#args[@]} == 0 )) && args=('.')
local -i args_n_1=${#args[@]}-1
for i in $(seq 0 $args_n_1); do
if (( ${#args[@]} > 1 )); then
(( i > 0 )) && echo
echo "${args[i]}:"
fi
(
shopt -s nullglob
cd "${args[i]}" &&
dirs=(*/) &&
(( ${#dirs[@]} > 0 )) &&
ls -d "${opts[@]}" "${dirs[@]%?}"
)
done
}
alias lsd=list_directories
此 lsd
可与任意数量的 ls
选项和目录自由混合使用。
$ lsd -h dir1 dir2 -rt ~
注意:当您将 glob 与 lsd
一起使用时,语义会发生变化。
lsd path/to/dir*
列出以“path/to/dir”开头的每个目录下的所有目录。
要列出所有以“path/to/dir”开头的目录,请使用普通的 ls -d path/to/dir*
.
this similar question 已经有很多答案了。但是 none 满足我的要求。我要
列出一个目录下的所有目录,不用glob(
*
)语法,即我想直接用lsdir somedir
输出应包含目录的基本名称,就像您使用
ls
时一样,例如:$ lsdir path/to/some/dir dir1 dir2 dir3 dir4
但不是这个:
$ lsdir path/to/dir path/to/dir/dir1 path/to/dir/dir2 path/to/dir/dir3 path/to/dir/dir4
为了满足要求 1,定义一个函数似乎是可行的,但无论如何我们将使用
-d
选项,列出ls
命令参数的目录本身。并且在使用
-d
选项时,ls
列出目录名称并在其父目录前加上前缀,如上所示。ls
格式(颜色、对齐、排序)应保留。为了满足要求 2,我们可以使用
find
但这样我们就失去了所有ls
输出格式,比如着色(基于自定义的 dircolors 主题)、对齐(输出对齐列)、排序(使用各种标志和列优先方式自定义排序),也许还有其他一些东西。
我知道同时想要这么多功能太贪心了,事实上我可以没有所有这些功能。
可以手动模拟 ls
输出格式,但这太不一致了。
我想知道是否有办法实现这一点并仍然利用 ls
,即如何使用 ls
.
这可能是您要找的:
cd path/to/dir && dirs=(*/) && ls -d "${dirs[@]%?}"
或者,也许
(shopt -s nullglob; cd path/to/dir && dirs=(*/) && ((${#dirs[@]} > 0)) && ls -d "${dirs[@]%?}")
第二个版本在子 shell 中运行,如果 path/to/dir
.
基于@M。 Nejat Aydin 的出色回答,我将进一步改进使其成为一个有用的命令,尤其是在处理选项和多个目录方面。
list_directories() {
local opts=()
local args=()
for i in $(seq $#); do
if [[ "${!i}" == -* ]]; then
opts+=("${!i}")
else
args+=("${!i}")
fi
done
(( ${#args[@]} == 0 )) && args=('.')
local -i args_n_1=${#args[@]}-1
for i in $(seq 0 $args_n_1); do
if (( ${#args[@]} > 1 )); then
(( i > 0 )) && echo
echo "${args[i]}:"
fi
(
shopt -s nullglob
cd "${args[i]}" &&
dirs=(*/) &&
(( ${#dirs[@]} > 0 )) &&
ls -d "${opts[@]}" "${dirs[@]%?}"
)
done
}
alias lsd=list_directories
此 lsd
可与任意数量的 ls
选项和目录自由混合使用。
$ lsd -h dir1 dir2 -rt ~
注意:当您将 glob 与 lsd
一起使用时,语义会发生变化。
lsd path/to/dir*
列出以“path/to/dir”开头的每个目录下的所有目录。
要列出所有以“path/to/dir”开头的目录,请使用普通的 ls -d path/to/dir*
.