2. Filename Generation — Zsh 5.9.999.3-test documentation

# 2. Filename Generation

Otherwise known as globbing, filename generation is quite extensive in `zsh`. Of course, it has all the basics:

Example 2.1: Basic globs with ls

    % ls
    Makefile   file.pro   foo.o      main.o     q.c        run234     stuff
    bar.o      foo        link       morestuff  run123     run240     sub
    file.h     foo.c      main.h     pipe       run2       run303
    % ls *.c
    foo.c  q.c
    % ls *.[co]
    bar.o   foo.c   foo.o   main.o  q.c
    % ls foo.?
    foo.c  foo.o
    % ls *.[^c]
    bar.o   file.h  foo.o   main.h  main.o
    % ls *.[^oh]
    foo.c  q.c

Also, if the `EXTENDED_GLOB` option is set, some new features are activated. For example, the `^` character negates the pattern following it:

Example 2.2: EXTENDED_GLOB negation

    % setopt extendedglob
    % ls -d ^*.c
    Makefile   file.pro   link       morestuff  run2       run303
    bar.o      foo        main.h     pipe       run234     stuff
    file.h     foo.o      main.o     run123     run240     sub
    % ls -d ^*.*
    Makefile   link       pipe       run2       run240     stuff
    foo        morestuff  run123     run234     run303     sub
    % ls -d ^Makefile
    bar.o      foo        link       morestuff  run123     run240     sub
    file.h     foo.c      main.h     pipe       run2       run303
    file.pro   foo.o      main.o     q.c        run234     stuff
    % ls -d *.^c
    .rhosts   bar.o     file.h    file.pro  foo.o     main.h    main.o

An expression of the form `<`x-y`>` matches a range of integers:

Example 2.3: Integer range globs

    % ls run<200-300>
    run234  run240
    % ls run<300-400>
    run303
    % ls run<-200>
    run123  run2
    % ls run<300->
    run303
    % ls run<->
    run123  run2    run234  run240  run303

The `NUMERIC_GLOB_SORT` option will sort files with numbers according to the number. This will not work with `ls` as it resorts its arguments:

Example 2.4: NUMERIC_GLOB_SORT with echo

    % setopt numericglobsort
    % echo run<->
    run2 run123 run234 run240 run303

Grouping is possible:

Example 2.5: Grouped alternation globs

    % ls (foo|bar).*
    bar.o  foo.c  foo.o
    % ls *.(c|o|pro)
    bar.o     file.pro  foo.c     foo.o     main.o    q.c

Also, the string `**/` forces a recursive search of subdirectories:

Example 2.6: Recursive directory globs

    % ls -R
    Makefile   file.pro   foo.o      main.o     q.c        run234     stuff
    bar.o      foo        link       morestuff  run123     run240     sub
    file.h     foo.c      main.h     pipe       run2       run303

    morestuff:

    stuff:
    file  xxx   yyy

    stuff/xxx:
    foobar

    stuff/yyy:
    frobar
    % ls **/*bar
    stuff/xxx/foobar  stuff/yyy/frobar
    % ls **/f*
    file.h            foo               foo.o             stuff/xxx/foobar
    file.pro          foo.c             stuff/file        stuff/yyy/frobar
    % ls *bar*
    bar.o
    % ls **/*bar*
    bar.o             stuff/xxx/foobar  stuff/yyy/frobar
    % ls stuff/**/*bar*
    stuff/xxx/foobar  stuff/yyy/frobar

It is possible to exclude certain files from the patterns using the ~ character. A pattern of the form `*.c~bar.c` lists all files matching `*.c`, except for the file `bar.c`.

Example 2.7: Glob exclusion with tilde

    % ls *.c
    foo.c    foob.c    bar.c
    % ls *.c~bar.c
    foo.c    foob.c
    % ls *.c~f*
    bar.c

One can add a number of qualifiers to the end of any of these patterns, to restrict matches to certain file types. A qualified pattern is of the form

Example 2.8: Qualifier pattern form

    pattern(...)

with single-character qualifiers inside the parentheses.

Example 2.9: File type qualifiers

    % alias l='ls -dF'
    % l *
    Makefile    foo*        main.h      q.c         run240
    bar.o       foo.c       main.o      run123      run303
    file.h      foo.o       morestuff/  run2        stuff/
    file.pro    link@       pipe        run234      sub
    % l *(/)
    morestuff/  stuff/
    % l *(@)
    link@
    % l *(*)
    foo*        link@       morestuff/  stuff/
    % l *(x)
    foo*        link@       morestuff/  stuff/
    % l *(X)
    foo*        link@       morestuff/  stuff/
    % l *(R)
    bar.o       foo*        link@       morestuff/  run123      run240
    file.h      foo.c       main.h      pipe        run2        run303
    file.pro    foo.o       main.o      q.c         run234      stuff/

Note that `*(x)` and `*(*)` both match executables. `*(X)` matches files executable by others, as opposed to `*(x)`, which matches files executable by the owner. `*(R)` and `*(r)` match readable files; `*(W)` and `*(w)`, which checks for writable files. `*(W)` is especially important, since it checks for world-writable files:

Example 2.10: World-writable qualifiers

    % l *(w)
    bar.o       foo*        link@       morestuff/  run123      run240
    file.h      foo.c       main.h      pipe        run2        run303
    file.pro    foo.o       main.o      q.c         run234      stuff/
    % l *(W)
    link@   run240
    % l -l link run240
    lrwxrwxrwx  1 pfalstad       10 May 23 18:12 link -> /usr/bin/
    -rw-rw-rw-  1 pfalstad        0 May 23 18:12 run240

If you want to have all the files of a certain type as well as all symbolic links pointing to files of that type, prefix the qualifier with a `-`:

Example 2.11: Dash prefix follows symlinks

    % l *(-/)
    link@       morestuff/  stuff/

You can filter out the symbolic links with the `^` character:

Example 2.12: Filter out symlinks

    % l *(W^@)
    run240
    % l *(x)
    foo*        link@       morestuff/  stuff/
    % l *(x^@/)
    foo*

To find all plain files, you can use `.`:

Example 2.13: Plain file and pipe quals

    % l *(.)
    Makefile  file.h    foo*      foo.o     main.o    run123    run234    run303
    bar.o     file.pro  foo.c     main.h    q.c       run2      run240    sub
    % l *(^.)
    link@       morestuff/  pipe        stuff/
    % l s*(.)
    stuff/   sub
    % l *(p)
    pipe
    % l -l *(p)
    prw-r--r--  1 pfalstad        0 May 23 18:12 pipe

`*(U)` matches all files owned by you. To search for all files not owned by you, use `*(^U)`:

Example 2.14: Ownership qualifiers

    % l -l *(^U)
    -rw-------  1 subbarao       29 May 23 18:13 sub

This searches for setuid files:

Example 2.15: Setuid qualifier

    % l -l *(s)
    -rwsr-xr-x  1 pfalstad       16 May 23 18:12 foo*

This checks for a certain user’s files:

Example 2.16: User qualifier match

    % l -l *(u[subbarao])
    -rw-------  1 subbarao       29 May 23 18:13 sub