On Github matthewfranglen / zshexpn
Created by Matthew Franglen
Bash has pattern expansion
except you can't search all folders...
and you can't exclude files from the results...
and you can't match by file attributes.
In Bash you end up using the find command.
In ZSH you don't have to!
setopt extended_glob
Most of the patterns in this talk require extended globbing
Set this in your .zshrc!
* will match any file or folder
? will match any single letter
[abc] will match any letter in the list
**/ will match any contained folder
% ls -d **/ css/ css/shaders/ css/theme/source/ js/ lib/css/ ... css/print/ css/theme/ css/theme/template/ lib/ lib/font/ ...
It really matches zero or more folders
PATTERN~EXCLUSION
Anything matching the exclusion will not be returned
% ls *.* grunt.js index.html package.json README.md REVEAL.md % ls *.*~*.md grunt.js index.html package.json
It just removes the individual excluded paths from the result
Just apply them one after the other
% ls **/*.js~plugin/**/*.js~lib/**/*.js grunt.js js/reveal.js js/reveal.min.js
PATTERN~EXCLUSION(ATTRIBUTES)
Allows you to restrict the match by things other than filename
. will match only files
/ will match only directories
@ will match only symlinks
^ will reverse the match
% ls *(.) grunt.js index.html LICENSE package.json README.md ... % ls -d *(^.) css js lib plugin
You can match by file permissions...
You can match by owner...
You can match by modification date...
Check the zshexpn manual Glob Qualifiers section for more!
PATTERN~EXCLUSION(ATTRIBUTES ALTERATIONS)
Allows you to alter the results to match your desired use
:t will remove the leading directories from the path
:h will remove the last file or directory from the path
:e will remove everything but the file extension
:r will remove the file extension
% echo index.html(:t) index.html(:h) index.html(:e) index.html(:r) index.html . html index % echo css/print/paper.css(:t:r) paper
:s#FIND#REPLACE# will replace the first match
:gs#FIND#REPLACE# will replace all matches
% echo css/print/paper.css(:s#css#woo#) woo/print/paper.css % echo css/print/paper.css(:gs#css#woo#) woo/print/paper.woo
Any variable can have alterations applied to it
% a="Looks like a /path/to.me" % echo $a:h $a:t:r ${a:e} Looks like a /path to me
You can expand variables as if they were patterns
This can be useful for building queries
% a='*(.)' % ls $~a grunt.js index.html LICENSE package.json README.md ...
Remember to single quote the pattern to avoid early expansion!
(#FLAG)
Globbing Flags change the way text in your pattern matches files.
They can be placed anywhere in a pattern and take effect from that point on.
(#aFACTOR)
Much like many search engines, you can apply a fuzz factor to your pattern.
The factor allows for letter replacement, swapping, addition, and removal.
% ls (#a1)gwunt.js (#a3)git.js grunt.js grunt.js
(#i)
You can apply Globbing Flags to part of a pattern using brackets.
% ls (#i)readme.MD README.md % ls ((#i)readme).MD zsh: no matches found: ((#i)readme).MD
If you need to match in a way not covered here,
Or if you just want to use a more familiar tool
e:'CONDITION':
Executes the condition as shell code.
The current match to test is stored in $REPLY
% ls **/*(e:'[ $(mimetype -b $REPLY) = "text/x-markdown" ]':) css/theme/README.md README.md REVEAL.md
Remember to single quote the condition to prevent early expansion!
+FUNCTION NAME
Allows you to use a function for more complex conditions.
If the function returns true then the current file will be matched.
% function file_matcher () { hash=$(openssl md5 $REPLY | cut -d' ' -f2) [ $hash = "9dcf19ac58cdcf7952ae9444671b0fa6" ] } % ls **/*(.+file_matcher) js/reveal.js
As you can see, you can apply other restrictions too!
Assigning a new value to $REPLY will change the matched file.
But $reply is even better, as it can hold an array!
% function file_doubler () { reply=( $REPLY $REPLY ) # even assignment has a return value } % ls js/reveal.js(+file_doubler) js/reveal.js js/reveal.js
You can also change the result by applying the built in alterations after the matcher
All rights reserved
Do not distribute without permission
Github and Github Pages are permitted to distribute this