如何在 ls 中使用通配符来查找数字序列中缺少的文件?

如何在 ls 中使用通配符来查找数字序列中缺少的文件?

我正在尝试在终端中按顺序列出丢失的文件。虽然这里存在许多答案,但它们不够通用,我无法根据我的情况进行调整。因此,如果您可以做出一个足够通用且适合更多人的答案,请这样做。

我正在ls {369..422}.avi >/dev/null列出丢失的文件,但无法使用 * 来匹配以 .avi 结尾的任何文件。我怎样才能做到这一点?

数字不在文件末尾,而是在中间。所以我应该需要类似的东西*numbers*.avi

答案1

ls *{369..422}*.avi >/dev/null

这将首先生成类似的模式

*369*.avi
*370*.avi
*371*.avi
*372*.avi
*373*.avi
*374*.avi

通过大括号扩展,然后ls将使用这些模式执行,这将为每个无法扩展为当前目录中的名称的模式提供错误消息。

或者,如果您没有*名称中包含以下内容的文件:

for name in *{369..422}*.avi; do
    case "$name" in 
        '*'*) printf '"%s" not matched\n' "$name" ;;
    esac
done

这依赖于这样一个事实:如果模式与当前目录中的名称不匹配,则该模式将保持未展开状态。这为您提供了一种可能对丢失文件执行有用操作的方法,而无需解析ls.

答案2

如果你愿意*numbers*.avi,你可以这样做:

ls *[0-9]*.avi

指定一个字符类,由您的语言环境之间和语言环境中[0-9]的所有字符组成。这应该是所有数字。因此,您想要匹配 0 个或多个字符 ( ),然后匹配一个数字,然后再次匹配 0 个或多个字符 ( )。09*[0-9]*

如果您需要按顺序排列多个数字,请使用:

ls *[0-9][0-9]*.avi

最后,如果您有按数字顺序排列的文件并且只想找到丢失的文件,您还可以编写一个小循环:

for avi in {369..422}.avi; do [ -e "$avi" ] || echo "$avi missing"; done

答案3

要列出哪些模式*{369..422}*.avi与任何文件都不匹配,zsh您可以执行以下操作:

for p (\*{369..422}\*.avi) () {(($#)) || echo $p} $~p(N[1])

或者更详细地说:

for p (\*{369..422}\*.avi) () {
  if (($#)); then
    echo "$# file(s) matching $p"
  else
    echo >&2 No file matching $p
  fi
} $~p(N)

对于遵循固定模式(例如:)的文件foo-123-bar.avi,您还可以执行以下操作:

expected=(foo-{369..422}-bar.avi)
actual=($^expected(N))
missing=(${expected:|actual})
print -l $missing

其中的一些zsh特定功能:

  • x{1..20}y大括号扩展扩展为x1y, x2y.... 此后被其他一些 shell 复制。
  • for var (values) cmdfor:循环的简短形式
  • () compound-command args:匿名函数就像许多其他语言一样。
  • $~p:将 的内容视为$p一个全局变量(其他 shell 默认情况下会这样做,甚至会进行分词!)
  • (N[1]):glob 限定符,当它们不匹配任何文件时,glob 扩展为无参数。[1]只选择第一个匹配的文件,因为我们只有一个来判断是否有匹配。
  • $^array:数组中元素的大括号式扩展
  • ${array1:|array2}:数组减法
  • print -l:按行打印

答案4

您可以尝试: ls *{369..422}*.avi

相关内容