使用 shell 脚本列出前 3 个字母相同的文件,后跟 # 序列

使用 shell 脚本列出前 3 个字母相同的文件,后跟 # 序列

第一次在这里发帖。如何对目录中前 3 个字母相同且后跟序列号的文件进行分组?例如

VHS-01-001.avi
VHS-01-002.avi
-------------
VHS-02-001.avi
VHS-02-002.avi
VHS-02-003.avi
---------
Hi8-01-001.avi
Hi8-01-002.avi
Hi8-01-003.avi

这样我就可以在函数中传递每组视频文件,如下所示:

encode(){
  for avi in "$@" 
  do..
}

答案1

也许不是很聪明的解决方案:

  • 按名称对文件排序
  • 循环遍历名称
  • 比较最后一个循环的字符:

    last=""
    ls -1 $1 | sort | while read file; do
        sub=${file:0:3}
        [ "$last" != "$sub" ] && { echo "NEW GROUP"; last="$sub"; }
        echo "[$sub] $file"
    done
    

而不是回显收集数组内的文件名......

只是一个想法...示例输出:

NEW GROUP                                                                                                                                                                                                                                    
[Hi8] Hi8-01-002.avi                                                                                                                                                                                                                         
NEW GROUP                                                                                                                                                                                                                                    
[VHS] VHS-01-001.avi                                                                                                                                                                                                                         
[VHS] VHS-01-002.avi
[VHS] VHS-02-002.avi
NEW GROUP
[XZU] XZU

编辑1:基于安东尼·盖根的答案是避免在循环开始时使用管道并使用 bash 通配符。看看他的评论。

改进的脚本:

last=""
for file in *avi; do
    sub=${file:0:3}
    [ "$last" != "$sub" ] && { echo "NEW GROUP"; last="$sub"; }
    echo "[$sub] $file"
done

编辑2:

正如@所问陈东尼在他的第三条评论中:在这里您可以找到一个直接的解决方案来将收集的文件名解析为函数。有很多方法可以做到这一点。而且我在 bash 脚本编写方面没有太多经验......;)

#!/bin/bash

SOURCE_DIR="$1"
cd "$SOURCE_DIR" || { echo "could not read dir '$SOURCE_DIR'"; exit 1; }

function parseFiles() {
  echo "parsing files:"
  echo "$1"
}

last=""
declare -a fileGroup

for file in *avi; do
  # first 3 chars of filename
  sub=${file:0:3}

  if test -z "$last"; then
    # last is empty. first loop
    last="$sub"
  elif test "$last" != "$sub"; then
    # new file group detected, parse collected
    parseFiles "${fileGroup[*]}"
    # reset array
    fileGroup=()
    last="$sub"
  fi

  # append name to array
  fileGroup[${#fileGroup[@]}]=$file
done

parseFiles "${fileGroup[*]}"

答案2

zsh

files=(???-??-*.avi)
for prefix (${(Mu)files#???-??-}) encode $prefix*.avi

(或者encode ${(M)files:#$prefix*}

GNU shell ( bash) 和工具的等效项是:

while IFS= read -u3 -rd '' prefix; do
  encode "$prefix-"*.avi 3<&-
done 3< <(printf '%s\0' ???-??-*.avi | grep -oz '^...-..-' | sort -zu)

同样的原则。我们获取当前目录中与模式匹配的文件列表,提取匹配 ( / ) (regexp )???-??-*.avi的部分,唯一它们 ( / ),然后循环遍历该前缀列表。(M)grep -o???-??-...-..-(u)sort -u

相关内容