0

I have a question that may or may not have an answer in the form I am looking for, but any form will suffice.

I currently have a configuration file, in which I will use a shell command on that uses grep to find a specific line within the file, then I use sed to get all the text after a specific character. The remaining text is simply a file path that includes an environment variable. The output from the command returns something like this:

$LIGHTS_HOME/music/something.mp3

I then want to pipe that to mp3info to get usable meta data from the mp3 file. However, when I pipe that over to mp3info $LIGHTS_HOME doesn't expand to the actual file path it is correlated to. How can I expand it within one line? Is this even possible?

Here is my current command:

$ sudo grep -w "file_path =" /home/pi/lightshowpi/config/state.cfg | 
sed 's/.*= //' | sed  's|'\$LIGHTS_HOME'| '/home/pi/lightshowpi'|' |
xargs mp3info -p "Now Playing: %t by %a" | xargs sudo python /home/pi/lightshowpi/tweet/tweet.py

What the command is doing(I have edited the line so that it is easier to read, in use it will need to be a single line (preferably, I am open to multi line if needed):

the first line uses grep to find the line 'file_path =', which returns the line 'file_path = $LIGHTS_HOME/music/songname.mp3'

Which is then piped to sed which parses the statement and returns all characters after the '=', which returns in this case '$LIGHTS_HOME/music/songname.mp3'

From there I use a second sed command to replace $LIGHTS_HOME with its variable value '/home/pi/lightshowpi/'

Ideally I would like to get rid of this second sed statement in favor of something that evaluates '$LIGHTS_HOME' to its value '/home/pi/lightshowpi/'

Which will then be used by mp3info to get the meta data of the file, which is formatted as a stdout which then is piped to xargs which prepares the meta stdout into a stdin format that the python script uses and tweets the value with a few other emoticon characters (which the python script does without an issue)

However, instead of using a second sed command of substituting $LIGHTS_HOME for /home/pi/lightshowpi I would rather have $LIGHTS_HOME expanded since on other installations this variable could be set somewhere other than the home directory.

I think I should note, that I am trying this whilst in terminal, I am not putting this inside a shell script. I am unsure if that changes things, I am still doing my best to learn shell, but I believe that this may change things based on the errors I keep getting.

9
  • Thanks for the idea I will break it up and place a detailed description of what is needed. @thrig Dec 5, 2016 at 22:35
  • @don_crissti unfortunately the issue is that depending on the installation and setup $LIGHT_HOME could be /home/pi/lightshowpi or /root/some/other/directory Dec 5, 2016 at 23:54
  • @don_crissti this is going to be apart of an open source project and needs the functionality of being a universal command, and for inexplicable reasons would prefer to be a single line command unless it's not attainable and then could be manipulated into a sh script Dec 5, 2016 at 23:56
  • @don_crissti I'm sorry, this is what I was looking for, I somehow read the comment incorrectly. Your solution was clear, it was my problematic reading skills Dec 6, 2016 at 0:01
  • @don_crissti would you mind explaining how your suggested solution works? I mean Im all for working commands, but I would also like to understand what it is that is going on. mainly I am confused about /file_path =/!d;s|.*=||;s|\$LIGHTS_HOME|$LIGHTS_HOME|" given that 'file_path =' is within the state.cfg file I am assuming that this command with find 'file_path =' then return everything after it, then replace $LIGHTS_HOME with what I would believe is the expansion of $LIGHTS_HOME, for this example /home/pi/lightshowpi but would be /root/pi/lightshowpi for a different configured $LIGHTS_HOME Dec 6, 2016 at 0:16

3 Answers 3

2

With ZSH you can "perform parameter expansion, command substitution and arithmetic expansion" with the (e) parameter expansion flag on something in a given variable x (see zshexpn(1) for details):

x='$HOME/blablah'; echo $x; echo ${(e)x}

Or from a file:

echo '$HOME/fromfile' > afile
echo ${(e)$(<afile)}

This has various advantages over eval, depending on who has access to the configuration file and how naughty they are:

$ touch somefile
$ echo 'hi; rm somefile' > x
$ eval "echo `cat x`"       
hi
$ ls somefile
ls: somefile: No such file or directory
$ exec zsh
% touch somefile
% echo ${(e)$(<x)}
hi; rm somefile
% ls somefile
somefile
% 
3
  • So essentially I can have the first portion stored into X then type ; echo $x | mp3info and it would evaluate the $LIGHTS_HOME portion of the file path into the actual file path? Dec 5, 2016 at 21:35
  • I am thinking something along the lines of: filename = sudo grep -w "file_path =" /home/pi/lightshowpi/config/state.cfg | sed 's/.*= //' | sed 's|'\$LIGHTS_HOME'| '/home/pi/lightshowpi'|'; echo $filename | xargs mp3info -p "Now Playing: %t by %a" | sudo python /home/pi/lightshowpi/tweet/tweet.py would this be the proper usage you are suggesting? Dec 5, 2016 at 22:46
  • the command should be filename = sudo grep -w "file_path =" /home/pi/lightshowpi/config/state.cfg | sed 's/.*= //'; echo $filename | xargs mp3info -p "Now Playing: %t by %a" | sudo python /home/pi/lightshowpi/tweet/tweet.py however, when I tried this, i get the error filename: command not found Dec 5, 2016 at 22:55
1

Essentially, this line of code searches a configuration file /home/pi/lightshowpi/config/state.cfg for the line "file_path =" then expands the environment variable $SYNCHRONIZED_LIGHTS_HOME to its value and pipes it to mp3info which extracts the meta data from the MP3 file then pipes the string to a Python script that takes the arguments and removes unwanted characters while including emoticons from a Python emoji library to tweet to your account through twitters API.

sed '/file_path =/!d;s|.*= ||;s|$SYNCHRONIZED_LIGHTS_HOME|'"$SYNCHRONIZED_LIGHTS_HOME|" /home/pi/lightshowpi/config/state.cfg | xargs mp3info -p "Now Playing %t by %a" | xargs sudo python /home/pi/lightshowpi/tweet/tweet.py

The key to this command is using ! to exclude the 'file_path =' then using xargs for mp3info and tweet.py

I will be debugging the following /home/pi/lightshowpi/config/state.cfg use the same variable $SYNCHRONIZED_LIGHTS_HOME instead of /home/pi/lightshowpi to make this command universal for this open source project.

0

Assuming that you have the value $LIGHTS_HOME/music/something.mp3 in a variable $myvar

you can expand it via :

mp3info $(eval echo $myvar)
1
  • I have updated my question with my current command which works fine, but I'd rather have $LIGHTS_HOME expanded and I do not have it stored in a variable. Dec 5, 2016 at 21:30

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .