I meant to list all files recursively excluding AV1-encoded files.
But the exclusion pattern does not work as I expected:
/Volumes/X/C/New/studio/成长的烦恼 copy ❯ tree
.
├── 成zhang的fan恼-剧场版2000-欢乐家庭 _[HighQ-AV1 (Modified)-svt_av1_10bit-rf_28.00].mkv
├── 成zhang的fan恼-剧场版2000-欢乐家庭.mkv
├── 成zhang的fan恼-剧场版2004-西弗一家的归来 _[HighQ-AV1 (Modified)-svt_av1_10bit-rf_28.00].mkv
└── 成zhang的fan恼-剧场版2004-西弗一家的归来.mkv
1 directory, 4 files
/Volumes/X/C/New/studio/成长的烦恼 copy ❯ ls **/*.mkv~**/*AV1*
成zhang的fan恼-剧场版2000-欢乐家庭 _[HighQ-AV1 (Modified)-svt_av1_10bit-rf_28.00].mkv
成zhang的fan恼-剧场版2000-欢乐家庭.mkv
成zhang的fan恼-剧场版2004-西弗一家的归来 _[HighQ-AV1 (Modified)-svt_av1_10bit-rf_28.00].mkv
成zhang的fan恼-剧场版2004-西弗一家的归来.mkv
/Volumes/X/C/New/studio/成长的烦恼 copy ❯
However, it will work if I move those files into a subfolder:
/Volumes/X/C/New/studio/成长的烦恼 copy ❯ tree
.
└── New Folder With Items
├── 成zhang的fan恼-剧场版2000-欢乐家庭 _[HighQ-AV1 (Modified)-svt_av1_10bit-rf_28.00].mkv
├── 成zhang的fan恼-剧场版2000-欢乐家庭.mkv
├── 成zhang的fan恼-剧场版2004-西弗一家的归来 _[HighQ-AV1 (Modified)-svt_av1_10bit-rf_28.00].mkv
└── 成zhang的fan恼-剧场版2004-西弗一家的归来.mkv
2 directories, 4 files
/Volumes/X/C/New/studio/成长的烦恼 copy ❯ ls **/*.mkv~**/*AV1*
New Folder With Items/成zhang的fan恼-剧场版2000-欢乐家庭.mkv
New Folder With Items/成zhang的fan恼-剧场版2004-西弗一家的归来.mkv
Now I am confused here. Even Grok is confused too.
I mean the recursive globbing pattern **/*something seems to fail and only fail for matching files directly under ./ when it comes after ~, which is strange to me.
Does anyone know what is wrong here?
From Mac Terminal Zsh
tl;dr - use this:
setopt extendedglob
print -l **/(*.mkv~*AVI*)
The recursive **/ operator is actually shorthand for (*/)#, i.e. */, grouped together with (...), repeated zero or more times (#). The biggest difference is that **/ does not require extendeglob to be set, whereas the # operator does.
However, the short version is only available in some circumstances. The phrasing in the documentation is that "the ‘*’ operators revert to their usual effect." The docs there don't address this situation explicitly, but that's what is happening.
Therefore **/*.mkv~**/*AV1* is really the same as **/*.mkv~*/*AV1*. It says to recursively find the *.mkv files, and then exclude files that match __/__AVI__. Only files in subdirectories will match that pattern.
Changing the pattern to the non-shortcut form will get you a bit closer:
print -l **/*.mkv~(*/)#*AVI*
Now any files with AVI anywhere in the name will be excluded, including those in the base directory. However, this ends up giving the same results as **/*.mkv~*AVI*, and will also exclude any directories that have AVI in the name. That's usually not the intended result.
This occurs because the pattern to the right of the ~ does not treat / as a special character. For a variety of reasons, the shell treats / differently in a 'glob' pattern, while it's simply another character in a 'match' pattern.
With this difference in mind, we can restructure the pattern as "files in any directory (**/*.mkv)", treating / as special, combined with "no AVI in the final component (~*AVI*)."
With parens added for grouping, we end up with this:
print -l **/(*.mkv~*AVI*)