我刚刚了解到 ls 无法处理通配符(ls '*'
不起作用),因此 shell 在调用 ls 之前执行此操作。因此,对于使用 UNIX 工作了 20 年的人来说,ls 的行为可能被认为是合乎逻辑的,但对我来说则不是,而且我不喜欢 ls。
我想要一个扫描文件和目录的目录命令然后应用通配符过滤器。这样 als cr*
不会列出目录“cron.daily”内的文件。
我知道有ls -d
,我做了一个alias lx=ls -lartd
。但后来我意识到,ls -d
出于某种秘密原因而没有任何争论根本行不通。
我可以安装任何替代品吗?
答案1
您可以使用find
,它(在许多平台上)有一个-ls
选项。所以你可以做
find . -maxdepth 1 -name '*' -ls
但如果很难记住ls -d
,你可能找不到find
改进。
答案2
如果您想要的是一个cmd
可以cmd cr*
列出cron.daily
自身的命令,那么该命令就是ls -d
。如果输入太多,您可以定义一个别名。例如,将此行放入您的~/.bashrc
:
alias l='ls -d'
然后运行l cr*
将显示有关cron.daily
其自身的信息,同时ls cr*
将列出目录的内容cron.daily
(以及与模式匹配的任何其他目录和与模式匹配的任何其他非目录)。
ls -d
确实有效。它完全按照您的要求进行操作:它列出了当前目录本身。这可能不是很有用——ls -ld
有点用,但不是ls -d
——但是计算机会做你告诉它们做的事情,它们不会读懂你的想法来找出你想要什么。
如果您想要获得 的效果ls -d
,除了不带参数您获得当前目录的列表之外,您可以定义一个函数。
l () {
if [ $# -eq 0 ]; then
ls -l
else
ls -ld "$@"
fi
}
然后l cr*
列出名称以 开头的文件cr
,即使它们是目录。并l cron.daily
列出cron.daily
其本身,而不是其内容;您可以使用ls cron.daily
或l cron.daily/*
列出内容。而是l
列出当前目录中的文件。
通过上面的函数,l -a
将传递-d
标志。如果您不想这样做,可以让函数在确定是否有文件名参数时放弃选项。
l () {
local a
a=("$@")
while [[ $1 = -* ]]; do shift; done
if [ $# -eq 0 ]; then
ls -l "${a[@]}"
else
ls -ld "${a[@]}"
fi
}
如果你想要的是一个命令cmd
来cmd cron.daily
列出子目录中的文件cron.daily
,但cmd cd*
列出cron.daily
它自己,那么这在 bash 中是不可能的。当命令执行时,shell 已经扩展了通配符,并且命令无法知道您是否使用了通配符。
这可以在桀骜,因为在 zsh 中您可以禁用特定命令的通配符扩展。 Zsh 不是大多数系统上的默认 shell,但只需安装一个软件包即可。在 zsh 中,您可以使用以下命令定义别名noglob
字首:
alias l='noglob list_files_or_directory_contents'
然后,您需要定义该list_files_or_directory_content
函数 - 您的要求并不常见,因此它可能还不存在。我认为这是一个功能,可以满足您的需求:列出直接指定的目录的内容,并列出目录本身(如果它们来自通配符扩展)。
list_files_or_directory_contents () {
local arg matches
setopt local_options no_csh_null_glob no_null_glob no_nomatch no_glob_subst no_sh_word_split
if (($#==0)); then
# No arguments: list the directory itself
ls -l
else
for arg; do
matches=($~arg)
if [[ $#matches -eq 1 && $matches[1] == $arg ]]; then
# Not a wildcard pattern: list the directory contents if it's a directory
ls -l -- $arg
else
# Wildcard pattern: list the matches themselves, even the ones that are directories
ls -ld -- $matches
fi
done
fi
}
答案3
我想这会做你想做的。我想,这种方法可以应用于您想要的任意数量的公用事业。但我真的不建议这样做,因为当您转移到尚未调整的新系统时,它会打破您的“手指习惯”。
ls() { [[ 0 == $# ]] && set -- *; /bin/ls -d "$@"; }
通过扩展,您的别名将被替换为以下函数:
lx() { [[ 0 == $# ]] && set -- *; /bin/ls -lartd "$@"; }