views:

3478

answers:

5

I have a portion of a bash script that is getting a filename without extension, but I'm trying to understand what is really going on here. What are the "%%"'s for? Can someone elaborate on what bash is doing behind the scenes? How can this technique be used on a general basis?

#!/bin/bash

for src in *.tif
    do
    txt=${src%%.*}
    tesseract ${src} ${txt}
    done
+1  A: 

Check out "Parameter Expansion" in the bash man pages. That syntax expands the $src variable deleting stuff that matches the .* pattern from it.

PEZ
Thank you, I didn't realize the bash man pages were so extensive.
jjclarkson
+9  A: 

It gets rid of the filename extension (here: .tif), sample:

$ for A in test.py test.sh test.xml test.xsl; do echo "$A: ${A%%.*}"; done
test.py: test
test.sh: test
test.xml: test
test.xsl: test

from bash manual:

   ${parameter%%word}
          The word is expanded to produce a pattern just as in pathname expansion.  If the
          pattern matches a trailing portion of the expanded value of parameter, then  the
          result  of  the  expansion  is the expanded value of parameter with the shortest
          matching pattern (the ``%'' case) or the longest matching  pattern  (the  ``%%''
          case) deleted.  If parameter is @ or *, the pattern removal operation is applied
          to each positional parameter in turn, and the expansion is the  resultant  list.
          If  parameter  is an array variable subscripted with @ or *, the pattern removal
          operation is applied to each member of the array in turn, and the  expansion  is
          the resultant list.
Johannes Weiß
From your example I can start to see how powerful bash can be right from the command line. Thanks!
jjclarkson
+3  A: 

Here's output from the bash man page

 ${parameter%%word}
          The word is expanded to produce a pattern just  as  in  pathname
          expansion.   If  the  pattern  matches a trailing portion of the
          expanded value of parameter, then the result of the expansion is
          the  expanded value of parameter with the shortest matching pat-
          tern (the ``%'' case)  or  the  longest  matching  pattern  (the
          ``%%''  case)  deleted.   If  parameter  is  @ or *, the pattern
          removal operation is applied to  each  positional  parameter  in
          turn,  and the expansion is the resultant list.  If parameter is
          an array variable subscripted with @ or *, the  pattern  removal
          operation  is  applied  to each member of the array in turn, and
          the expansion is the resultant list.
Steve Lazaridis
+1  A: 

It's a string removal operation in the format: ${str%%substr}

Where str is the string you are operating on, and substr is the pattern to match. It looks for the longest match of substr in str, and removes everything from that point on.

Jeff
+2  A: 

Apparently bash has several "Parameter Expansion" tools which include:

Simply substituting the value...

${parameter}

Expanding to a sub-string...

${parameter:offset}
${parameter:offset:length}

Substitute the length of the parameters value...

${#parameter}

Expanding upon a match at the beginning of the parameter...

${parameter#word}
${parameter##word}

Expanding upon a match at the end of the parameter...

${parameter%word}
${parameter%%word}

Expands the parameter to find and replace a string...

${parameter/pattern/string}

These are my interpretation of the parts I think I understand from this section of the man pages. Let me know if I missed something important.

jjclarkson
Just realize there's a slightly subtle difference between # and ## and % and %%. These expansions also do not understand filenames.
johnny