Bash – Continuous String Manipulation

#!/bin/bash

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

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

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

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

test:

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

script contents:

bash-$ cat test.sh 
#!/usr/bin/bash

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

echo "$FILE"

Method 2

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:

FILE=${${1:t}/%.jpeg/.jpg}

Method 3

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)

Method 4

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

FILE=$(sed 's/.*///;s/.jpeg$/.jpg/' <<<"$1")

Method 5

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.)

Method 6

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.

Method 7

The line

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

can be shortened and made more portable with

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


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x