How to use fnmatch from a shell?
1119 Репутация автора
In a generic shell script, I would like to use shell pattern matching to filter the lines of a text file.
I have a list of file names in files.txt:
file1.txt file2.sh file3.png
And I have a list of patterns in patterns.txt:
If I would have regular expressions in patterns.txt, I could do this:
$ grep -v -f patterns.txt files.txt
But I would like to use shell globbing patterns. I found the C function fnmatch but no shell/unix command to use it.Автор: maikel Источник Размещён: 29.12.2014 05:04
3840 Репутация автора
OK, this is going to be really unperformant, as POSIX sh does not even have arrays (which I would have used for caching the patterns):
while IFS= read -r filename; do hasmatch=0 while IFS= read -r pattern; do case $filename in ($pattern) hasmatch=1; break ;; esac done <patterns.txt test $hasmatch = 1 || printf '%s\n' "$filename" done <files.txt
If you don’t need the positional arguments (
$2, …) you can abuse those for pattern caching though:
saveIFS=$IFS; IFS=' '; set -o noglob set -- $(cat patterns.txt) IFS=$saveIFS; set +o noglob while IFS= read -r filename; do hasmatch=0 for pattern in "$@"; do case $filename in ($pattern) hasmatch=1; break ;; esac done test $hasmatch = 1 || printf '%s\n' "$filename" done <files.txt
Be careful about whitespace there though: we set
IFS to a literal newline character and nothing else, i.e.
I’ve tested this with your dataset plus a few additions (like a
a b* pattern, to test whitespace behaviour), and it seems to work for me according to the spec in the OP.