Bash: Renaming files using shell parameter expansion

Shell parameter expansion provides various ways to manipulate strings, and a convenient way to succinctly express renaming a set of files.

In its simplest form, parameter expansion is simply ${parameter}.  But look at these examples:

$ mystr="TheQuickBrownFox.jpg"

# chop off last 4 digits
$ echo ${mystr:0:-4}
TheQuickBrownFox

# truncate end of string '.jpg'
$ echo ${mystr%.jpg}
TheQuickBrownFox

# replace 'Fox' with 'Wolf'
$ echo ${mystr/Fox/Wolf}
TheQuickBrownWolf.jpg

# strips starting with 'Q' and stopping at 'ck'
$ echo ${mystr/Q*ck/}
TheBrownFox.jpg

Armed with string expansion, let’s create a set of files that follows the pattern “index-X.temp.html”.

$ for i in $(seq 1 3); do touch index-$i.temp.html; done

$ ls *.html
index-1.temp.html  index-2.temp.html  index-3.temp.html

And now rename the files in this directory to instead use the pattern “default-X.htm”

$ or orig in $(ls *.html);do newname=${orig/index/default}; mv $orig ${newname%.temp.html}.htm; done

$ ls *.htm
default-1.htm  default-2.htm  default-3.htm

Notice the intermediate variable to do the first replacement of ‘index’ with ‘default’.  Then the suffix truncation starting with ‘.temp.html’.

 

REFERENCES

gnu.org, shell parameter expansion

stackoverflow, rename multiple files

cyberciti, bash shell param substitution like a pro

devhints.io, parameter expansion cheat sheet

 

NOTES

Extracting filename from full file path

$ for fullpath in $(find . | xargs realpath); do echo ${fullpath##*/}; done
tmp
default-1.htm
default-2.htm
default-3.htm

Excluding name from full file path

$ for fullpath in $(find . | xargs realpath); do echo ${fullpath%/*}; done

/home/fabian
/home/fabian/tmp
/home/fabian/tmp
/home/fabian/tmp

Only filename part of URL

$ url="https://fabianlee.org/downloads/test-1.2.3.gz" && echo ${url##*/}
test-1.2.3.gz

Only base URL part

$ url="https://fabianlee.org/downloads/test-1.2.3.gz" && echo ${url%/*}
https://fabianlee.org/downloads

Parameter expansion for replacement

# some versions of wget do not like no_proxy domains
# being prefixed with "." 
# curl does not have this issue
export http_proxy=http://mysquid:3128
export https_proxy=$http_proxy
export no_proxy=127.0.0.1,localhost,.foo.com,.bar.com
# replace all ",." with just comma to get rid of period
no_proxy=${no_proxy//,./,} wget https://mydomain.foo.com

replacing dash with period

FULL_ID="mysubdomain-maindomain-com"
# replace just first dash
echo ${FULL_ID/-/.}
# replace all dashes
echo ${FULL_ID//-/.}

replacing period with dash

ISTIO_VERSION=1.7.5
# single forward slash would mean only replace one
ISTIO_VERSION_HYPHENATED=${ISTIO_VERSION//\./\-}

removing whitespace

# remove leading whitespace
output="${output##*( )}"
# remove trailing whitespace
output="${output%%*( )}"