Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

FILE="$(basename "$1")"

Is there anyway to glue these two lines together into a one-liner?

share|improve this question
up vote 11 down vote accepted

FILE=$(basename "${1/%.jpeg/.jpg}") worked for me.


bash-$ ./test.sh /tmp/foo.jpeg

script contents:

bash-$ cat test.sh 

FILE=$(basename "${1/%.jpeg/.jpg}")

echo "$FILE"
share|improve this answer
Since the two lines are kinda interchangable, this solution is so far the neatest... If the lines aren't interchangable sed will be definitely needed I guess. – gsklee Nov 8 '11 at 22:21

You can't nest expansions in bash (nor in ksh, ash and other shells apart from zsh). This is only a cosmetic limitation, since as you illustrate you can assign an intermediate expression to a temporary variable. It is a little annoying for one-liners, but in scripts it's arguably better for readability.

You could avoid using the external utility basename and use a string manipulation construct instead:

FILE="${1##*/}"; FILE="${FILE/%.jpeg/.jpg}"

Here, it happens that you can rewrite your script to put the command substitution on the outside. That's not a general phenomenon, nor do you gain anything other than a certain one-liner feeling.

Zsh, for better or for worse, does let you nest expansions:

FILE=${$(basename $1)/%.jpeg/.jpg}    # using basename
FILE=${${1##*/}/%.jpeg/.jpg}          # using string rewriting

Or you could use zsh's built-in construct instead of basename:

share|improve this answer

You could use a single sed command as in the following:

FILE=$(sed 's/.*\///;s/\.jpeg$/.jpg/' <<<"$1")
share|improve this answer

Incorporating sed, this should do the trick:

FILE="$(basename "$1" | sed s/\.jpeg$/.jpg/)"

(This doesn't exactly answer your question because I can't; not sure if it's possible.)

share|improve this answer

The Bash ${} constructs work with variable names, so there's no way to embed a command directly. @sr_'s approach is an alternative if you don't mind the extra fork.

share|improve this answer

The line

FILE=$(basename "${1/%.jpeg/.jpg}")

can be shortened and made more portable with

FILE=$(basename "${1%.jpeg}.jpg")
share|improve this answer

I'd go for :

FILE=$(basename $1 .jpeg).jpg

The second parameter to basename is a suffix to be removed from the file name (see man basename)

share|improve this answer
+1 for introducing extra parameter – warl0ck Sep 26 '12 at 0:44

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.