sed does not what I expect it to do

sed does not what I expect it to do

I want to do simple string replacements with sed to rename some files. Unfortunately it does not work the way I expect. My Input (these files):

'Djrum - Under Tangled Silence - 01 A Tune For Us.flac'
'Djrum - Under Tangled Silence - 02 Waxcap.flac'
'Djrum - Under Tangled Silence - 03 Unweaving.flac'
"Djrum - Under Tangled Silence - 04 L'Ancienne.flac"
'Djrum - Under Tangled Silence - 05 Hold.flac'
'Djrum - Under Tangled Silence - 06 Galaxy In Silence.flac'
'Djrum - Under Tangled Silence - 07 Reprise.flac'
'Djrum - Under Tangled Silence - 08 Three Foxes Chasing Each Other.flac'
'Djrum - Under Tangled Silence - 09 Let Me.flac'
'Djrum - Under Tangled Silence - 10 Out Of Dust.flac'
'Djrum - Under Tangled Silence - 11 Sycamore.flac'

My command:

for file in *.flac ; do a=(` echo "$file" | sed -rE 's/Djrum - Under Tangled Silence - // ; s/ /./ ' `) ; echo mv  "$file" "$a" ; done

My output:

mv Djrum - Under Tangled Silence - 01 A Tune For Us.flac 01.A
mv Djrum - Under Tangled Silence - 02 Waxcap.flac 02.Waxcap.flac
mv Djrum - Under Tangled Silence - 03 Unweaving.flac 03.Unweaving.flac
mv Djrum - Under Tangled Silence - 04 L'Ancienne.flac 04.L'Ancienne.flac
mv Djrum - Under Tangled Silence - 05 Hold.flac 05.Hold.flac
mv Djrum - Under Tangled Silence - 06 Galaxy In Silence.flac 06.Galaxy
mv Djrum - Under Tangled Silence - 07 Reprise.flac 07.Reprise.flac
mv Djrum - Under Tangled Silence - 08 Three Foxes Chasing Each Other.flac 08.Three
mv Djrum - Under Tangled Silence - 09 Let Me.flac 09.Let
mv Djrum - Under Tangled Silence - 10 Out Of Dust.flac 10.Out
mv Djrum - Under Tangled Silence - 11 Sycamore.flac 11.Sycamore.flac

Note the 1st, 8th, 9th and 10th result. I tried it on this site: Read more, where I get the correct results. What am I doing wrong?

Answer

Your code includes:

a=(` echo "$file" | sed -rE 's/Djrum - Under Tangled Silence - // ; s/ /./ ' `)

which does not do what you probably intend.

It says:

  • `...` - run a command and return the output
  • a=(...) - assign the words in ... as the elements of an array
    • by default, words are split on spaces, so a will contain multiple elements

Note that if a is an array, referring to $a is the same as referring to ${a[0]}

Consider:

$ x=(`echo "a  b  c"`)
$ declare -p x
declare -a x=([0]="a" [1]="b" [2]="c")
$ echo $x
a
$

To fix your problem, quote the output of command. Better yet, don't use an array:

$ y=("`echo "a  b  c"`")
$ declare -p y
declare -a y=([0]="a  b  c")
$ z=`echo "d  e  f"`
$ declare -p z
declare -- z="d  e  f"
$

You may want to use s/ /./g or s/[[:space:]]/./g so that all spaces are converted and not just the first.

Enjoyed this article?

Check out more content on our blog or follow us on social media.

Browse more articles