How can I use inverse or negative wildcards when pattern matching in a unix/linux shell?

前端 未结 11 1606
梦如初夏
梦如初夏 2020-11-22 13:50

Say I want to copy the contents of a directory excluding files and folders whose names contain the word \'Music\'.

cp [exclude-matches] *Music* /target_direc         


        
11条回答
  •  醉酒成梦
    2020-11-22 14:24

    The following works lists all *.txt files in the current dir, except those that begin with a number.

    This works in bash, dash, zsh and all other POSIX compatible shells.

    for FILE in /some/dir/*.txt; do    # for each *.txt file
        case "${FILE##*/}" in          #   if file basename...
            [0-9]*) continue ;;        #   starts with digit: skip
        esac
        ## otherwise, do stuff with $FILE here
    done
    
    1. In line one the pattern /some/dir/*.txt will cause the for loop to iterate over all files in /some/dir whose name end with .txt.

    2. In line two a case statement is used to weed out undesired files. – The ${FILE##*/} expression strips off any leading dir name component from the filename (here /some/dir/) so that patters can match against only the basename of the file. (If you're only weeding out filenames based on suffixes, you can shorten this to $FILE instead.)

    3. In line three, all files matching the case pattern [0-9]*) line will be skipped (the continue statement jumps to the next iteration of the for loop). – If you want to you can do something more interesting here, e.g. like skipping all files which do not start with a letter (a–z) using [!a-z]*, or you could use multiple patterns to skip several kinds of filenames e.g. [0-9]*|*.bak to skip files both .bak files, and files which does not start with a number.

提交回复
热议问题