【发布时间】:2016-09-12 12:34:00
【问题描述】:
我正在编写一个 bash 脚本,该脚本需要在与特定扩展名不匹配的目录中循环文件。到目前为止,我发现以下代码会循环所有与给定扩展名匹配的文件:
for f in *.txt ; do
echo $f;
done
insthead 如何遍历与指定扩展名不匹配的文件?
【问题讨论】:
-
你可以使用
^(.*[^\.txt])$
我正在编写一个 bash 脚本,该脚本需要在与特定扩展名不匹配的目录中循环文件。到目前为止,我发现以下代码会循环所有与给定扩展名匹配的文件:
for f in *.txt ; do
echo $f;
done
insthead 如何遍历与指定扩展名不匹配的文件?
【问题讨论】:
^(.*[^\.txt])$
您可以使用 == 运算符进行模式匹配。
for f in *; do
[[ $f == *.txt ]] && continue
# [[ $f != *.txt ]] || continue
...
done
如果这可能在空目录中运行,请在循环之前使用shopt -s nullglob,或者将[ -e "$f" ] || continue 放在循环中。 (前者更可取,因为它避免不断检查文件是否存在。)
【讨论】:
[ -e "$f" ] || continue
[ -e "$f" ] 将始终成功,因为 $f 是通过路径名扩展设置的。
*
循环目录中不匹配特定扩展名的文件
你可以使用extglob:
shopt -s extglob
for f in *.!(txt); do
echo "$f"
done
pattern *.!(txt) 将匹配所有带有点且点后没有 txt 的条目。
编辑:请参阅下面的 cmets。这是一个find 版本,用于循环当前目录中与特定扩展名不匹配的文件:
while IFS= read -d '' -r f; do
echo "$f"
done < <(find . -maxdepth 1 -type f -not -name '*.txt' -print0)
【讨论】:
mkdir -p foo; touch foo/file.1.txt; shopt -s extglob; echo foo/*.!(txt)
find -type f。 (见更新)
for 循环中也跳过子目录
这样就可以了:
shopt -s extglob
for f in !(*.txt) ; do
echo $f
done
您只需使用 !(glob_pat) 反转 glob 模式,要使用它,您需要启用扩展 glob。
如果你想忽略目录,那么:
shopt -s extglob
for f in !(*.txt) ; do
[ -d "$f" ] && continue # This will ignore dirs
# [ -f "$f" ] && continue # This will ignore files
echo $f
done
如果你想进入所有子目录,那么:
shopt -s extglob globstar
for f in !(*.txt) **/!(*.txt) ; do
[ -d "$f" ] && continue # This will ignore dirs
# [ -f "$f" ] && continue # This will ignore files
echo $f
done
【讨论】:
做
find /path/to/look -type f -not -name "*.txt" -print0 | while read -r -d '' file_name
do
echo "$file_name"
done
当您的文件名可能不标准时。
注意:
如果您不希望递归搜索子文件夹中的文件,请在 -type f 之前添加 -maxdepth 1
。
【讨论】:
如果您可以接受GNU 解决方案,请尝试一下:
for f in $(find . -maxdepth 1 -type f \! -name \*.txt) ; do
printf "%s\n" "${f}"
done
如果文件名中包含特殊字符,例如(空格),这将会中断。
为了安全,还是GNU,试试吧:
find . -maxdepth 1 -type f \! -name \*.txt -printf "%p\0" | xargs -0 sh -c '
for f ; do
printf "%s\n" "${f}"
done' arg0
【讨论】:
for f in $(ls --hide="*.txt")
do
echo $f
done
【讨论】: