Bash: loop through files that DO NOT match extension

后端 未结 6 359
眼角桃花
眼角桃花 2021-01-13 17:32

I\'m writing a bash script that needs to loop files inside a directory that do not match a specific extension. So far, I\'ve found that the following code loops all files th

相关标签:
6条回答
  • 2021-01-13 17:57

    to loop files inside a directory that do not match a specific extension

    You can use 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.


    EDIT: Please see comments below. Here is a find version to loop through files in current directory that don't match a particular extension:

    while IFS= read -d '' -r f; do
        echo "$f"
    done < <(find . -maxdepth 1 -type f -not -name '*.txt' -print0)
    
    0 讨论(0)
  • 2021-01-13 18:00

    If you are ok for a GNU solution, give a try to this:

    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:

    find . -maxdepth 1 -type f \! -name \*.txt -printf "%p\0" | xargs -0 sh -c '
        for f ; do
          printf "%s\n" "${f}"
        done' arg0
    
    0 讨论(0)
  • 2021-01-13 18:04

    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
    just before -type f.

    0 讨论(0)
  • 2021-01-13 18:09

    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.

    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
    
    0 讨论(0)
  • 2021-01-13 18:17

    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 in side the loop. (The former is preferable, as it avoids constantly checking if a file exists.)

    0 讨论(0)
  • 2021-01-13 18:23
    for f in $(ls --hide="*.txt")
    do
        echo $f
    done
    
    0 讨论(0)
提交回复
热议问题