如何查找具有特定扩展名但文件名中不包含某些字符的文件列表?
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.txt
和 L-004_45.txt
都存在。所以我想获取名称中没有 45 的文本文件列表。
我该怎么做?
我尝试使用 find
和 ls
并成功了,但我想知道如何改为使用 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的ext
endedglob
ing
#!/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
我有一个文件夹,其中包含具有扩展名的文件,例如 .txt
、.sh
和 .out
。
但是,我想要一个只有 .txt
扩展名的文件列表, 和 不包含某些字符的文件名。
例如,.txt
个文件被命名为 L-003_45.txt
等等,直到 L-003_70.txt
。有些文件在 L-003
部分发生了变化,假设 L-004
,创建了假设文件 45 的副本,因此基本上 L-003_45.txt
和 L-004_45.txt
都存在。所以我想获取名称中没有 45 的文本文件列表。
我该怎么做?
我尝试使用 find
和 ls
并成功了,但我想知道如何改为使用 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的ext
endedglob
ing
#!/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