.. _intro_zsh_filename_generation:

Filename Generation
===================

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

.. code-block:: text
   :caption: Basic globs with ls
   :name: filename_generation_basic_globs

   % 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

.. _EXTENDED_GLOB:

.. index:: single: EXTENDED_GLOB

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

.. code-block:: text
   :caption: EXTENDED_GLOB negation
   :name: filename_generation_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 :literal:`<`\ :emphasis:`x`-\ :emphasis:`y`\ :literal:`>` matches a range of integers:

.. code-block:: text
   :caption: Integer range globs
   :name: filename_generation_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

.. _NUMERIC_GLOB_SORT:

.. index:: single: NUMERIC_GLOB_SORT

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

.. code-block:: text
   :caption: NUMERIC_GLOB_SORT with echo
   :name: filename_generation_numeric_glob_sort

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

Grouping is possible:

.. code-block:: text
   :caption: Grouped alternation globs
   :name: filename_generation_grouped_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 :literal:`**/` forces a recursive search of subdirectories:

.. code-block:: text
   :caption: Recursive directory globs
   :name: filename_generation_recursive_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 :literal:`*.c~bar.c` lists all files matching :literal:`*.c`, except for the file :literal:`bar.c`.

.. code-block:: text
   :caption: Glob exclusion with tilde
   :name: filename_generation_glob_exclusion

   % 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 :emphasis:`qualifiers` to the end of any of these patterns, to restrict matches to certain file types.  A qualified pattern is of the form

.. code-block:: text
   :caption: Qualifier pattern form
   :name: filename_generation_qualifier_form

   pattern(...)

with single-character qualifiers inside the parentheses.

.. code-block:: text
   :caption: File type qualifiers
   :name: filename_generation_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 :literal:`*(x)` and :literal:`*(*)` both match executables. :literal:`*(X)` matches files executable by others, as opposed to :literal:`*(x)`, which matches files executable by the owner. :literal:`*(R)` and :literal:`*(r)` match readable files; :literal:`*(W)` and :literal:`*(w)`, which checks for writable files. :literal:`*(W)` is especially important, since it checks for world-writable files:

.. code-block:: text
   :caption: World-writable qualifiers
   :name: filename_generation_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 :literal:`-`:

.. code-block:: text
   :caption: Dash prefix follows symlinks
   :name: filename_generation_qualifier_dash_prefix

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

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

.. code-block:: text
   :caption: Filter out symlinks
   :name: filename_generation_filter_symlinks

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

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

.. code-block:: text
   :caption: Plain file and pipe quals
   :name: filename_generation_plain_file_qualifiers

   % 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

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

.. code-block:: text
   :caption: Ownership qualifiers
   :name: filename_generation_ownership_qualifiers

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

This searches for setuid files:

.. code-block:: text
   :caption: Setuid qualifier
   :name: filename_generation_setuid_qualifier

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

This checks for a certain user's files:

.. code-block:: text
   :caption: User qualifier match
   :name: filename_generation_user_qualifier

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