是否有可以处理通配符的“ls”替代品?

是否有可以处理通配符的“ls”替代品?

我刚刚了解到 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.dailyl 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
}

如果你想要的是一个命令cmdcmd 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 "$@"; }

相关内容