简体   繁体   English

Bash:循环遍历与扩展名不匹配的文件

[英]Bash: loop through files that DO NOT match extension

I'm writing a bash script that needs to loop files inside a directory that do not match a specific extension. 我正在编写一个bash脚本,需要在目录中循环与特定扩展名不匹配的文件。 So far, I've found that the following code loops all files that matches the given extension: 到目前为止,我发现以下代码循环所有匹配给定扩展名的文件:

for f in *.txt ; do
    echo $f;
done

How could insthead loop through files that do not match the specified extension? insthead如何循环遍历与指定扩展名不匹配的文件?

You can pattern-match with the == operator. 您可以使用==运算符进行模式匹配。

for f in *; do
    [[ $f == *.txt ]] && continue
    # [[ $f != *.txt ]] || continue
    ...
done

If this might run in an empty directory, either use shopt -s nullglob prior to the loop, or put [ -e "$f" ] || continue 如果这可能在空目录中运行,则在循环之前使用shopt -s nullglob ,或者放入[ -e "$f" ] || continue [ -e "$f" ] || continue in side the loop. 循环[ -e "$f" ] || continue (The former is preferable, as it avoids constantly checking if a file exists.) (前者更可取,因为它可以避免不断检查文件是否存在。)

to loop files inside a directory that do not match a specific extension 循环目录中与特定扩展名不匹配的文件

You can use extglob : 你可以使用extglob

shopt -s extglob

for f in *.!(txt); do
    echo "$f"
done

pattern *.!(txt) will match all entries with a dot and no txt after the dot. pattern *.!(txt)将匹配所有带点后的条目,并且点后没有txt


EDIT: Please see comments below. 编辑:请参阅下面的评论。 Here is a find version to loop through files in current directory that don't match a particular extension: 这是一个循环查看当前目录中与特定扩展名不匹配的文件的find版本:

while IFS= read -d '' -r f; do
    echo "$f"
done < <(find . -maxdepth 1 -type f -not -name '*.txt' -print0)

Do

find /path/to/look -type f -not -name "*.txt" -print0 | while read -r -d '' file_name
do
echo "$file_name"
done

when your filenames may be nonstandard. 当你的文件名可能是非标准的。

Note: 注意:

If you don't wish to recursively search for files in subfolders include -maxdepth 1 如果您不希望以递归方式搜索子文件夹中的文件,请包括-maxdepth 1
just before -type f . 就在前-type f

This will do: 这样做:

shopt -s extglob
for f in !(*.txt) ; do
    echo $f
done

You just inverse the glob pattern using !(glob_pat) , and to use it, you need to enable extended glob. 你只需使用!(glob_pat)反转glob模式,并使用它,你需要启用扩展的glob。

If you want to ignore directories, then: 如果要忽略目录,则:

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

If you wanna go into all sub-dirs then: 如果你想进入所有子目录,那么:

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

If you are ok for a GNU solution, give a try to this: 如果您对GNU解决方案没问题,请试试这个:

for f in $(find . -maxdepth 1 -type f \! -name \*.txt) ; do
  printf "%s\n" "${f}"
done

This is going to break if special chars are contained in the filenames, such as 如果文件名中包含特殊字符,则会中断,例如 (space). (空间)。

For something safe, still GNU , try: 对于安全的东西,仍然是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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM