LinuxQuestions.org
Go Job Hunting at the LQ Job Marketplace
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - Newbie
User Name
Password
Linux - Newbie This Linux forum is for members that are new to Linux.
Just starting out and have a question? If it is not in the man pages or the how-to's this is the place!

Notices

Reply
 
Search this Thread
Old 12-05-2012, 11:28 PM   #1
kitsftw
LQ Newbie
 
Registered: Dec 2012
Posts: 4

Rep: Reputation: Disabled
Exporting "select d" output to a separate variable


Hit a real wall with trying to set a new variable after a select statement. Highlighted where I hit my wall in red:

Code:
#!/bin/sh

## User defined variables

        read -p "Path to Client's Public HTML Directory (e.g. /mnt/data/www/domainname.com): " DIRROOT
        read -p "New name for the Custom theme, lowercase, no spaces (e.g. customtheme or custom_theme: " THEMENAMELC
        read -p "New name for the Custom theme, Uppercase, May contain Spaces (e.g. User Custom Theme): " THEMENAMEUC


## Define additional varibles from user defined item(s)

        THEMEDIR=$DIRROOT/theme
        DATAROOT=$(grep -i '^$CFG->dataroot' $DIRROOT/config.php | sed "s|^.*'\(.*\)';.*|\1|")
        NEWTHEMEDIR=$DATAROOT/theme

## Enter the directory listed above

        cd $THEMEDIR

### User will define which theme they would like provided as an editable theme

        PS3="Enter the # of the theme you would like to make editable: "
        select d in */;
                do
        echo "You picked $d ($REPLY), it is now being made editable for the client."

## Redfine "d" to strip the "/"

        OLDTHEMENAME=$(echo "$d" | cut -d'/' -f1)

## Create the NEWTHEMEDIR if it does not exist

        echo "Step 1: Creating new Theme directory in Moodledata if it does not exist..."

        if [! -d $NEWTHEMEDIR]; then
        mkdir -p $NEWTHEMEDIR;
        fi;

## Move the new theme into the editable theme directory

        echo "Step 2: Moving choosen theme to new Moodledata directory..."

	rsync -a $d $NEWTHEMEDIR/$THEMENAMELC

## Change the contents of all files containing the old theme name

	echo "Step 3: Changing the contents of all files containing the old theme name..."

	cd $NEWTHEMEDIR/$THEMENAMELC
	grep -lr -e '$OLDTHEMENAME' * | xargs sed -i 's|$OLDTHEMENAME|$THEMENAMELC|g'

    
done

exit
Is it possible to define a new variable in the manor I am attempting to do so? As you can see later on in the script I am attempting to use the defined output, which I thought would be the directory name without the suffix '/', to alter contents of a file with sed.

What I am attempting is likely more easily accomplished with php but I am attempting to learn new bash tricks. Any help would be much appreciated!
 
Old 12-06-2012, 12:23 AM   #2
chrism01
Guru
 
Registered: Aug 2004
Location: Sydney
Distribution: Centos 6.5, Centos 5.10
Posts: 16,289

Rep: Reputation: 2034Reputation: 2034Reputation: 2034Reputation: 2034Reputation: 2034Reputation: 2034Reputation: 2034Reputation: 2034Reputation: 2034Reputation: 2034Reputation: 2034
Looks ok to me; did you get a problem?
You may find bash has more capabilities than sh.

It seemed to work with this basic test
Code:
#!/bin/sh
select d in */
do echo $d
    OLDTHEMENAME=$(echo "$d" | cut -d'/' -f1) 
    echo $OLDTHEMENAME 
    if [[ -d $OLDTHEMENAME ]]
    then
        echo "is a dir"
    fi
done
As I said, I'd prob use bash instead. For debugging, 'set -xv' is good thus
Code:
#!/bin/bash
set -xv
HTH
 
1 members found this post helpful.
Old 12-06-2012, 07:33 AM   #3
kitsftw
LQ Newbie
 
Registered: Dec 2012
Posts: 4

Original Poster
Rep: Reputation: Disabled
Thanks for the assist Chrisand thank you for that debugging command! That will be a life saver for troubleshooting and did not even think to use such a tool. (facepalm) I was able to confirm that it did indeed set the variable properly but the problem arose with the sed command. I probably should of mentioned that before but was a bit tired

Here is the debugging output:

Code:
Step 3: Changing the contents of all files containing the old theme name...
+ cd /mnt/data/username/theme/test
+ xargs sed -i 's|orginaltheme|test|g'
+ grep -lr -e '$OLDTHEMENAME' config.php lang layout lib.php pix pix_core pix_plugins renderers.php settings.php style version.php
sed: no input files
It appears that my "grep | sed" is being passed to the terminal opposite from what I had intended. However I thought that doing "grep | sed" would pass grep first and then modify the results with the sed command not run sed first, resulting in the "sed: no input files".

Original grep | sed:

Code:
grep -lr -e '$OLDTHEMENAME' * | xargs sed -i 's|'$OLDTHEMENAME'|'$THEMENAMELC'|g'

Last edited by kitsftw; 12-06-2012 at 07:35 AM.
 
Old 12-06-2012, 09:58 AM   #4
ntubski
Senior Member
 
Registered: Nov 2005
Distribution: Debian
Posts: 2,494

Rep: Reputation: 850Reputation: 850Reputation: 850Reputation: 850Reputation: 850Reputation: 850Reputation: 850
The trouble is you are single quoting your variables instead of double quoting them.

Code:
# here you use single quotes because you are looking for dollar sign followed by "CFG",
# not the value of variable $CFG.
# Technically, you should escape the $ because it's a special character
# for grep that matches end of line, but it seems like GNU grep at least
# interprets $ literally when it's followed by more text.
# Also, you should generally double quote every use of variables to avoid word splitting.
DATAROOT=$(grep -i '^\$CFG->dataroot' "$DIRROOT/config.php" | sed "s|^.*'\(.*\)';.*|\1|")

...

# here you are searching for the string contained in the variable $OLDTHEMENAME
# so you should use double quotes
grep -lr -e "$OLDTHEMENAME" * | xargs sed -i "s|$OLDTHEMENAME|$THEMENAMELC|g"
Quote:
However I thought that doing "grep | sed" would pass grep first and then modify the results with the sed command not run sed first, resulting in the "sed: no input files".
Technically, when you have a pipeline all the programs are running in parallel, but the programs later in the pipeline usually need to wait for input from earlier programs before they can do anything.


Code:
        if [! -d $NEWTHEMEDIR]; then
        mkdir -p $NEWTHEMEDIR;
        fi;
Did the above not give any errors? The "[" and "]" need to be space separated. But you actually don't need the if at all: mkdir -p checks if the directory exists already.
 
1 members found this post helpful.
Old 12-06-2012, 04:18 PM   #5
kitsftw
LQ Newbie
 
Registered: Dec 2012
Posts: 4

Original Poster
Rep: Reputation: Disabled
Quote:
Originally Posted by ntubski View Post
The trouble is you are single quoting your variables instead of double quoting them....

Code:
        if [! -d $NEWTHEMEDIR]; then
        mkdir -p $NEWTHEMEDIR;
        fi;
Did the above not give any errors? The "[" and "]" need to be space separated. But you actually don't need the if at all: mkdir -p checks if the directory exists already.
Thanks for the knowledge. The double quoting solved the issue. Yeah, I figured I could just get rid of the if statement due to the inherent check by mkdir -p. Did not know if it was more acceptable to run it as a if statement when creating scripts. Then again it is always best to take the shortest route to solution in scripts so, that answers that question . The code I linked did produce an error, yes, due to the improper formatting. Forgot to update the original post to address that typo.

Again, thank you both for all the help!
 
Old 12-07-2012, 06:10 AM   #6
David the H.
Bash Guru
 
Registered: Jun 2004
Location: Osaka, Japan
Distribution: Debian sid + kde 3.5 & 4.4
Posts: 6,823

Rep: Reputation: 1948Reputation: 1948Reputation: 1948Reputation: 1948Reputation: 1948Reputation: 1948Reputation: 1948Reputation: 1948Reputation: 1948Reputation: 1948Reputation: 1948
As mentioned before, you could make some things easier if you used bash instead of sh. Is it possible for you to do so, or does it have to be POSIX portable?

In any case I want to go over a few lines and cover some important coding points:

1)
Code:
#!/bin/sh
As mentioned, /bin/sh forces the script to be interpreted according to POSIX standards. To (reliably) use another shell's features you need to explicitly specify it, i.e. #!/bin/bash.

2)
Code:
read -p "..." DIRROOT
This is a minor point, but since environment variables are generally all upper-case, it's good practice to keep your own user variables in lower-case or mixed-case to help differentiate them.


3)
Code:
DATAROOT=$(grep -i '^$CFG->dataroot' $DIRROOT/config.php | sed "s|^.*'\(.*\)';.*|\1|")
a. As mentioned, single quotes don't allow variable expansion. But in addition, unquoted variables ($DIRROOT) are subject to word splitting and glob expansion. This is a very important scripting point, so learn it well!

http://mywiki.wooledge.org/Arguments
http://mywiki.wooledge.org/WordSplitting
http://mywiki.wooledge.org/Quotes

b. There's usually no need to use chains of grep/sed/awk, etc. sed can do its own line matching, and awk can do the job of both of the other two.

Code:
DATAROOT=$( sed -rn "/^$CFG->dataroot/I s|^.*'(.*)';.*|\1|p"  "$DIRROOT/config.php" )
( I believe "I" may be a gnu extension, however, and perhaps also the -r option that lets you avoid having to backslash advanced regex syntax. )

I'm also a little concerned about your sed regex. Since "*" is greedy, it may match more than you expect it to. But I'd have to see some examples of the text to say for sure.

c. You really should be running some tests on your user input to make sure that you were given proper file/directory names before you use them like this.

4)

Code:
OLDTHEMENAME=$( echo "$d" | cut -d'/' -f1 )
You should be able to use parameter substitution instead of cut here. The basic ones should be available to all shells, at least.

Code:
OLDTHEMENAME=${d%%/*}
5)
Code:
if [! -d $NEWTHEMEDIR]; then
mkdir -p $NEWTHEMEDIR;
fi;
a. As mentioned, watch the spaces when using the test construct.

b. Again, be sure to properly quote your variables.

c. If you're using bash, then it's recommended to use the expanded [[..]] test for string/file tests, and ((..)) for numerical tests. Avoid using the old [..] test unless you specifically need POSIX-style portability.

d. Re your previous post, The if statement isn't really necessary here, but it does have the minor benefit of slightly lightening the processing load, as the external mkdir command will only be run if needed.

e. Clean, consistent formatting makes code readable and more easily debuggable. Be liberal with whitespace; indent all your sub-commands evenly and separate logical sections with empty lines. Never just line everything up on the left edge.

Scripting With Style

6)
Code:
grep -lr -e '$OLDTHEMENAME' * | xargs sed -i 's|$OLDTHEMENAME|$THEMENAMELC|g'
a. Quoting again.

b. When processing filenames, particularly with xargs, you should really use null separators. Although this depends on your tools having support for them.

Assuming the gnu versions of the tools, I believe you can do this:
Code:
grep -lr -Z -e '$OLDTHEMENAME' * | xargs -0 sed -i "s|$OLDTHEMENAME|$THEMENAMELC|g"
If you aren't using the gnu toolset, check your documentation to see if null separators are supported.

7)
Code:
exit
I recommend always supplying an explicit exit value, rather than relying on the default, which is the exit status of the final command run.

Code:
exit 0
 
1 members found this post helpful.
Old 12-07-2012, 05:36 PM   #7
kitsftw
LQ Newbie
 
Registered: Dec 2012
Posts: 4

Original Poster
Rep: Reputation: Disabled
Thank you all for the information and knowledge. I was aware that linuxquestions.org users were helpful but everything you all did was above and beyond! @David the H. - Lessons learned and back to the drawing board I go! I am still working through my advanced lesson on *nix systems and this is my first crack at bash. Think I am going to hit the library for a bash 101 before I go any deeper into the rabbit hole and end up mangling my web application badly.
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
bash script: using "select" to show multi-word options? (like "option 1"/"o zidane_tribal Programming 6 03-21-2013 10:35 AM
Socket Programming making use of "select()" and "writefds" johncsl82 Programming 10 11-13-2011 12:27 PM
Skip "Installation Method" and "Select Partition" screens using boot options tclappsdba Linux - Newbie 1 11-26-2010 05:31 AM
square brackets in output of "ps aux" not matching output of "ps -ejH" alirezan1 Linux - Newbie 14 07-14-2010 04:17 AM
How to get the "data type" of an "unknown variable" in "C Language" ? Affair Programming 8 06-20-2009 12:30 PM


All times are GMT -5. The time now is 07:13 PM.

Main Menu
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
identi.ca: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration