[SOLVED] bash script: can echo command, command works if I type, but command doesn't work in script ... why?
My goal is to understand what is going on:
The following script is given the name 'marg': ------------------------------------------------ #!/bin/bash d=$(dirname "$1") b=$(basename "$1") echo find "$d" -name ""$b"" -type f -print ------------------------------------------------ If I type marg './foo/*' bar/ in an xterm, the result is find ./foo -name "*" -type f -print If I type the above command into an xterm it executes ok. But if I change marg to ------------------------------------------------ #!/bin/bash d=$(dirname "$1") b=$(basename "$1") find "$d" -name ""$b"" -type f -print ------------------------------------------------ then If I type marg './foo/*' bar/ in an xterm, the result is that the find command does not execute. WHY? P.S. For those wondering "what am I trying to do?" the answer is: I am trying to understand what is going on with the above. P.P.S. I have spent time looking online and reading man pages, but I obviously do not understand the fundamental principles... could some kind soul walk me through exactly what is going on and why removing the echo from the script does not result in the find command working? |
Remove the second set of quotes around $b in your find, they're messing things up. I think your intention is to add quotes into the command, but of course you can't nest quotes like that. "" is just an empty string, so you have [empty string]*[empty string]. Since the asterisk isn't quoted, it's being treated as a globbing pattern, rather than a literal asterisk, which is screwing up the find.
Also, add "set -x" at the top of your script after the shebang for testing things like this. Code:
#!/bin/bash |
Thanks... I think you got me over my sticking point.
|
Code:
bash -x /path/to/script.sh |
A few additional thoughts
If you needed to use echo (e.g. if there were other strings to add ... )
Code:
echo "I found [" $(find "$d" -name "$b" -type f -print) "]" Also, note that your example Code:
marg './foo/*' bar/ Since your script only has one argument, the second one is ignored (after it is expanded). That's why you don't see bar anywhere in your example output. In line with @habitual's suggestion, I have a file called bash_trace in my ~/bin directory which contains: Code:
shopt -s -o xtrace # debug Code:
##source "~/bin/bash_trace" ## debug The source statement or just plain . tells bash to read that file as if it was part of the script - just like an include statement in other languages. The shopt sets shell options. (There are a lot of them.) -s stands for set or turn on and -o says which option to affect. verbose is the same as the -v command line option which prints shell command lines as they are read. xtrace is the same as the -x command line option which prints the command line after it has been expanded. This lets you see the command the way you wrote it and then shows you what "marvelous" things bash did to expand it before actually trying to execute it. |
Install the bashdb package for your distro, and use it to single-step through scripts, inspect variables, etc. It's not perfect but it's usually quite informative, especially if you put -xv on your hashbang inside the script being debugged.
|
some additional thoughts
[QUOTE=hopeless_n00b;5491087]My goal is to understand what is going on:
The following script is given the name 'marg': ...skip #!/bin/bash d=$(dirname "$1") b=$(basename "$1") find "$d" -name ""$b"" -type f -print ------------------------------------------------ ...skip then If I type marg './foo/*' bar/ ...skip =========================== In your initial question you use: marg './foo/*' bar/ Legacy bash states that something enclosed in apostrophes is to be taken litterly and those between quotes is to be expanded. for those who had bad English teachers: ..apostrophe(s) is/are also referred to as single quote(s) ..quote(s) is/are also referred to as double quote(s). since you are using bash to differentiate the path and the filename anyway, you probably should simply make the marge call: ..marge "./foo/*bar" #assumes filename ends in anythingbar ... or ..marge "./foo/*.bar" #assumes filename ends in .bar ... or ..marge "./foo/*bar*" #assumes seeking anythingbaranything the echo should be removed because find could return a few thousand matches and -print does the echo part anyway. :) I add the echo to the front of search loop commands to check if the loop is going to do what I think it will rather than what it actually got told. :) Once bash and I agree on the desired results I remove the echo from the front of the command line (the find line in your case) and send it off to work. Norseman01 |
Hi. "" Are special characters. All you put between them are literal. You can put "'" and "" or "$" when you need show those specials characters (if you have a variable VARIABLE, you can show variable contents with:
echo $VARIABLE or show variable name with: echo "$VARIABLE" Without "", \ convert next character from special in normal, for example, in empty space: HI\ MY\ NAME Try with: VAR1="HI MY NAME" ; echo $VAR1; unset VAR1; echo $VAR1 VAR1=HI\ MY\ NAME ; echo $VAR1; unset VAR1; echo $VAR1 VAR1=HI MY NAME ; echo $VAR1; unset VAR1; echo $VAR1 VAR1=HI"" MY"" NAME ; echo $VAR1; unset VAR1; echo $VAR1 VAR1=HI"\ "MY "\ "NAME ; echo $VAR1; unset VAR1; echo $VAR1 and you can see differences. You can find lot of combinations with special characters (" , ' , \ , $ , % , & ; etc) in: man bash Have a nice day. |
Quote:
double quotes do not prevent variable substitution. echo $VARIABLE and echo "$VARIABLE" will provide the exact same output. single quotes are what prevents variable substitution. |
Please use Thread tools to actually mark the question as SOLVED
|
solved
Thanks a lot. I have always used echo to see what my command will actually look like. However set -x should be used to see what actual command is running.
|
All times are GMT -5. The time now is 03:16 AM. |