157

I have been searching to find a way to convert a string value from uppercase to lowercase. All the search results show approaches of using the tr command.

The problem with the tr command is that I am able to get the result only when I use the command with the echo statement. For example:

y="HELLO"
echo $y| tr '[:upper:]' '[:lower:]'

The above works and results in 'hello', but I need to assign the result to a variable as below:

y="HELLO"
val=$y| tr '[:upper:]' '[:lower:]'
string=$val world

When assigning the value like above it gives me an empty result.

PS: My Bash version is 3.1.17

2
  • for files: cat file_name | tr '[:upper:]' '[:lower:]' >> lower
    – mccurcio
    Commented Oct 14, 2021 at 19:12
  • I needed to use val=$(echo $y | tr '[:upper:]' '[:lower:]') rather than just val=$y| tr '[:upper:]' '[:lower:]' Commented Mar 25, 2023 at 17:32

7 Answers 7

260

If you are using Bash 4, you can use the following approach:

x="HELLO"
echo $x  # HELLO

y=${x,,}
echo $y  # hello

z=${y^^}
echo $z  # HELLO

Use only one , or ^ to make the first letter lowercase or uppercase.

10
  • 2
    Thanks for your immediate response. When i tried the above it says ${y,,}--bad substitution. Any how i tried another approach of y="HI" val = $( tr '[A-Z]' '[a-z]' <<< $y) and this worked for me.Thanks once again
    – raga
    Commented Jul 9, 2012 at 9:55
  • 10
    Your bash version too low. It doesn't support those features.
    – kev
    Commented Jul 9, 2012 at 9:58
  • 8
    The ,, ^^ substitutions only work on bash 4, not bash 3 so you'd need to upgrade bash or use the tr approach.
    – Ian
    Commented Oct 21, 2013 at 9:52
  • 2
    If bad substitution message is returned, also check if you accidentally wrote '$' before variable name (${$y,,} instead of ${y,,}), which results in the same error as when bash version is too low (you can check it with 'bash --version').
    – BartekM
    Commented Oct 17, 2016 at 12:15
  • 5
    I was confused for a moment because I was doing bash --version and getting 5.0.3, but then realized that was brew version of bash (at /usr/local/bin/bash). My script had my system bash in the header with #!/bin/bash which was version 3 :( Commented Jan 21, 2020 at 19:59
94

One way to implement your code is

y="HELLO"
val=$(echo "$y" | tr '[:upper:]' '[:lower:]')
string="$val world"

This uses $(...) notation to capture the output of the command in a variable. Note also the quotation marks around the string variable -- you need them there to indicate that $val and world are a single thing to be assigned to string.

If you have Bash 4.0 or higher, a more efficient & elegant way to do it is to use Bash built-in string manipulation:

y="HELLO"
string="${y,,} world"
0
41

Note that tr can only handle plain ASCII, making any tr-based solution fail when facing international characters.

Same goes for the Bash 4-based ${x,,} solution.

The AWK tool, on the other hand, properly supports even UTF-8 / multibyte input.

y="HELLO"
val=$(echo "$y" | awk '{print tolower($0)}')
string="$val world"

Answer courtesy of liborw.

1
  • 1
    Thanks. Options with tr didn't work for me. Might be a MacOS/BSD thing.
    – TastyWheat
    Commented Mar 2, 2022 at 15:37
26

Execute in backticks:

 x=`echo "$y" | tr '[:upper:]' '[:lower:]'` 

This assigns the result of the command in backticks to the variable x. (I.e., it's not particular to tr, but it is a common pattern/solution for shell scripting.)

You can use $(..) instead of the backticks. See here for more info.

3
  • 5
    Thanks a lot for your answer. the above works..to make it better i tried y="HI" val = $( tr '[A-Z]' '[a-z]' <<< $y) and it worked fine for me..Thank you once again for your suggestion
    – raga
    Commented Jul 9, 2012 at 9:51
  • 1
    @raga <<< - love it!!! much more elegant than echo "overkill" ☺︎
    – msciwoj
    Commented Dec 5, 2014 at 12:09
  • 1
    Just remember that \$, double backslash and backslash backtick will not be treated literally with backticks, but they will inside $(..). That could be good or bad depending on your usecase. tldp.org/LDP/Bash-Beginners-Guide/html/sect_03_04.html Section 3.4.5.
    – Jeremy
    Commented Jun 5, 2015 at 20:55
11

I'm on Ubuntu 14.04 (Trusty Tahr), with Bash version 4.3.11. However, I still don't have the fun built-in string manipulation ${y,,}

This is what I used in my script to force capitalization:

CAPITALIZED=`echo "${y}" | tr '[a-z]' '[A-Z]'`
4
  • Does the shebang line at the top of your script point to an older version of bash?
    – Tan Wang
    Commented Feb 19, 2017 at 18:55
  • No, I only have one version installed on my system, so it points to the system default bash.
    – BoomShadow
    Commented Feb 21, 2017 at 14:11
  • I think that the [] are not required: unix.stackexchange.com/questions/51983/… Commented May 9, 2018 at 16:27
  • 1
    ${y,,} won't work in Ubuntu if you use #!/bin/sh since the default shell is Dash. You must use #!/bin/bash Commented Mar 22, 2021 at 15:44
8

If you define your variable using declare (old: typeset) then you can state the case of the value throughout the variable's use.

declare -u FOO=AbCxxx
echo $FOO

Output:

ABCXXX

Option -l to declare does lowercase:

When the variable is assigned a value, all upper-case characters are converted to lower-case. The upper-case attribute is disabled.

4
  • 2
    Not in Bash 3.2
    – Amit Naidu
    Commented May 24, 2019 at 21:49
  • 2
    Bash 3.2 was released on 2006-10-11 (nearly 16 years ago). That was before Shellshock was (officially) discovered (2014). Commented Jun 21, 2022 at 11:37
  • @Amit Naidu: What system are you using? Commented Jun 21, 2022 at 11:52
  • works with local too Commented May 11 at 13:38
5

Building on Rody's answer, this worked for me.

y="HELLO"
val=$(echo $y | tr '[:upper:]' '[:lower:]')
string="$val world"

One small modification: if you are using underscore next to the variable, you need to encapsulate the variable name in {}.

string="${val}_world"
1
  • Is it only underscore (not a rhetorical question)? What about other punctuation, like comma? Commented Jun 21, 2022 at 11:11

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