如何查找具有特定扩展名但文件名中不包含某些字符的文件列表?

How to find a list of files that are of specific extension but do not contain certain characters in their file name?

我有一个文件夹,其中包含具有扩展名的文件,例如 .txt.sh.out

但是,我想要一个只有 .txt 扩展名的文件列表, 不包含某些字符的文件名。

例如,.txt 个文件被命名为 L-003_45.txt 等等,直到 L-003_70.txt。有些文件在 L-003 部分发生了变化,假设 L-004,创建了假设文件 45 的副本,因此基本上 L-003_45.txtL-004_45.txt 都存在。所以我想获取名称中没有 45 的文本文件列表。

我该怎么做?

我尝试使用 findls 并成功了,但我想知道如何改为使用 for loop

我试过: for FILE in *.txt; do ls -I '*45.txt'; done 但失败了。

非常感谢您的帮助!

我建议您使用 find 命令查找具有所需扩展名的所有文件,然后过滤掉具有“奇怪”字符的文件,例如用于查找文件扩展名:

find ./ -name "*.txt" -o -name "*.sh" -o name "*.out"

...现在,为了不显示名称中带有“45”的那些,您可以这样做:

find ./ -name "*.txt" -o -name "*.sh" -o name "*.out" | grep -v "45"

...如果您不想使用“45”或“56”,您可以:

find ./ -name "*.txt" -o -name "*.sh" -o name "*.out" | grep -v "45" | grep -v "56"

解释:

  • -o代表OR
  • grep -v 代表“--invert-match”(不显示这些结果)

设置:

$ touch L-004_23.txt L-003_45.txt L-004_45.txt L-003_70.txt

$ ls -1 L*txt
L-003_45.txt
L-003_70.txt
L-004_23.txt
L-004_45.txt

使用 ! 否定标准的一个想法:

$ find . -name "*.txt" ! -name "*_45.txt"
./L-003_70.txt
./L-004_23.txt

find 结果提供给 while 循环,例如:

while read -r file
do
    echo "file: ${file}"
done < <(find . -name "*.txt" ! -name "*_45.txt")

这会生成:

file: ./L-003_70.txt
file: ./L-004_23.txt

或者你使用Bash的extendedglobing

#!/usr/bin/env bash

# Enables extended globing
shopt -s extglob

# Prevents iterating patterns if no match found
shopt -s nullglob

# Iterates files not having 45 or 57 before .txt
for file in !(*@(45|57)).txt; do
  printf '%s\n' "$file"
done

extglob 提出的解决方案非常好。如果您需要排除多个模式,您也可以测试并继续。排除所有 *45.txt*57.txt 的示例:

declare -a excludes=("45" "57")
for f in *.txt; do
  for e in "${excludes[@]}"; do
    [[ "$f" == *"$e.txt" ]] && continue 2
  done
  printf '%s\n' "$f"
done