FILENAME=$(echo /root/Source/code/script.sh | grep -oE "[^/]+$")

I know that it would give me the file name from the file path here as script.sh. But can some one please explain me this?


3 Answers 3


Let's count the number of mistakes in:

FILENAME=$(echo $INFILE | grep -oE "[^/]+$")
  1. echo should not be used for arbitrary data. Depending on the implementation, it will fail if $INFILE starts with - or contains backslashes or both.
  2. Leaving a variable unquoted is the split+glob operator. That will cause the above to fail for many possible values of $INFILE. Variables should never be left unquoted unless you've got a very good reason not to.
  3. grep works on each line of it's input, while here you want it to do it only the whole string.
  4. If $INFILE is /some/dir/ or /, that will return the empty string instead of dir or /.
  5. The -o option is GNU specific, so that will only work where grep is the GNU grep.
  6. cosmetic/convention: All Upper-case variable names should be reserved for environment variables.
  7. command substitution removes the trailing newline characters, so the above will not work if $INFILE ends in newline characters.

To get the base name of a file, there's a standard command for that:

filename=$(basename -- "$infile")

Or to avoid (7) above:

filename=$(basename -- "$infile"; echo .); filename=${filename%??}

Or, using shell expansion operators:


(still has problem (4) above).


[^/]+$ is a Regular Expression for "One or more of any character that is not a slash, followed by the end of the tested string". The string being tested is /root/Source/code/script.sh; the part of that string that matches the pattern is script.sh. grep -o returns only the matching pattern and not the entire line which matched.


-o means: Print only the matched (non-empty) parts of a matching line, with each such part on a separate output line.

[^/]+$ means: Match as many chars as possible to the right which do not contain a slash. That's the file name without the leading directories.

Usually this is done with:

basename /root/Source/code/script.sh

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .