How to made bash to execute variable value.
For example, we have this code, where variable value was set in single quotes(!).
#!/bin/bash
V_MY_PATH='$HOME'
echo "$V_MY_PATH"
ls $V_MY_PATH
The output is
$HOME
ls: $HOME: No such file or directory
How to made bash to translate shell variable insto its value if there is some.
I want to add some code after V_MY_PATH='$HOME' to make output like echo $HOME.
It's something simple, but i'm stuck.
(NB: I know that with V_MY_PATH="$HOME", it works fine.)
EDIT PART:
I just wanted to make it simple, but I feel that some details are needed.
I'm getting parameter from a file. This part works good. I don't want to rewite it.
The problem is that when my V_MY_PATH contains a predefined variable (like $home) it's not treated like its value.
Remove the single quotes
V_MY_PATH='$HOME'
should be
V_MY_PATH=$HOME
you want to use $HOME as a variable
you can't have variables in single quotes.
Complete script:
#!/bin/bash
V_MY_PATH=$HOME
echo "$V_MY_PATH"
ls "$V_MY_PATH" #; Add double quotes here in case you get weird filenames
Output:
/home/myuser
0
05430142.pdf
4
aiSearchFramework-7_10_2007-v0.1.rar
etc.
use variable indirect reference so:
pete.mccabe#jackfrog$ p='HOME'
pete.mccabe#jackfrog$ echo $p
HOME
pete.mccabe#jackfrog$ ls ${p}
ls: cannot access HOME: No such file or directory
pete.mccabe#jackfrog$ ls ${!p}
bash libpng-1.2.44-1.el6 python-hwdata squid
...
pete.mccabe#jackfrog$
The ${!p} means take the value of $p and that value is the name of the variable who's contents I wish to reference
Use eval command:
#!/bin/bash
V_MY_PATH='$HOME'
echo "$V_MY_PATH"
eval ls $V_MY_PATH
You can use single or double quotes, and in your case, none if you prefer.
You have nothing telling bash what the variable is equal to. Maybe something like this? (unless I misunderstand what you are trying to do)
======================================================================
#!/bin/bash
#########################
# VARIABLES #
#########################
V_MY_PATH=home
#########################
# SCRIPT #
#########################
echo "What is your home path?"
read $home
echo "Your home path is $V_MY_PATH"
ls $V_MY_PATH
Of course you could also just remove the variable at the top and use:
echo "Your home path is $home"
Related
I want to read a list of file names stored in a file, and the top level directory is a macro, since this is for a script that may be run in several environments.
For example, there is a file file_list.txt holding the following fully qualified file paths:
$TOP_DIR/subdir_a/subdir_b/file_1
$TOP_DIR/subdir_x/subdir_y/subdir_z/file_2
In my script, I want to tar the files, but in order to do that, tar must know the actual path.
How can I get the string containing the file path to expand the macro to get the actual path?
In the code below the string value echoed is exactly as in the file above.
I tried using actual_file_path=`eval $file_path` and while eval does evaluate the macro, it returns a status, not the evaluated path.
for file_path in `cat $input_file_list`
do
echo "$file_path"
done
With the tag ksh I think you do not have the utility envsubst.
When the number of variables in $input_file_list is very limited, you can substitute vars with awk :
awk -v top_dir="${TOP_DIR}" '{ sub(/$TOP_DIR/, top_dir); print}' "${input_file_list}"
I was using eval incorrectly. The solution is to use an assignment on the right side of eval as follows:
for file_path in `cat $input_file_list`
do
eval myfile=$file_name
echo "myfile = $myfile"
done
$myfile now has the actual expansion of the macro.
I want to make a new directory with the name of every zip file currently exists in a specific directory, in another one. I have written a 'for loop' for this purpose:
files=NL*.zip
for a in $files; do
b=echo $a;
sudo mkdir '/home/shokufeh/Desktop/normals/T1/"${b}"';
done
but it creates a directory named ${b} for the first round and make errors for next ones.
Could you please tell me what I should do?
You put your variable in simple quotes, there fore '${b}' will never be interpreted. Try this:
for a in NL*.zip; do
sudo mkdir "/home/shokufeh/Desktop/normals/T1/${a}";
done
No need for variables $files and $b.
To summarize, let's say var=3,
echo "$var" will display 3
echo '$var' will display $var
echo "'$var'" will display '3'
echo '"$var"' will display "$var"
Hopefully this makes sense. Quotes function like parentheses and brackets.
I seem to be not able to get this right
When i run this code I need a variable for the filename later on. How should I do thi?
#!/bin/bash
foo="../../../data/audio/serval-data/wav-16bit-16khz/ytdl/balanced_train/vidzyGjrJfE_rg.wav"
echo $foo
echo "${foo%.*}" | cut -d "/" -f10;
# fid=vidzyGjrJfE_rg
I want to use new variable fid to have value "vidzyGjrJfE_rg"
You can use a couple of iterations of shell builtins for this (see #melpomene's answer) but FYI that's exactly what basename exists to do:
$ foo="../../../data/audio/serval-data/wav-16bit-16khz/ytdl/balanced_train/vidzyGjrJfE_rg.wav"
$ fid=$(basename "$foo" '.wav')
$ echo "$fid"
vidzyGjrJfE_rg
You can do it like this:
fid="${foo##*/}"
fid="${fid%.*}"
Just as % removes a matching suffix from a variable, # removes a prefix (and ## removes the longest matching prefix). See https://www.gnu.org/software/bash/manual/bashref.html#Shell-Parameter-Expansion.
I'm working on a script which checks if file exists. If it exists then I want to get the route.
What I did is the following:
RESULT_=$(find $PWD -name someRandom.json)
This returns the path to the file:
/Users/guest/workspace/random_repo/random/some_folder/someRandom.json
I'm stuck in the way to navigate among files. Is there a way of replacing someRandom.json with '' so I can do:
cd /Users/guest/workspace/random_repo/random/some_folder/
I tried using the solution provided here but it isn't working. I tried the following:
RESULT=$($RESULT/someRandom.json/'')
echo $RESULT
And this returns no such file or directory.
given:
$ echo "$result"
/Users/guest/workspace/random_repo/random/some_folder/someRandom.json
You can get the file name:
$ basename "$result"
someRandom.json
Or the path:
$ dirname "$result"
/Users/guest/workspace/random_repo/random/some_folder
Or you can use substring deletion:
$ echo "${result%/*}"
/Users/guest/workspace/random_repo/random/some_folder
Or, given the file name and the full path, just remove the file name:
$ echo "$tgt"
someRandom.json
$ echo "${result%"$tgt"}"
/Users/guest/workspace/random_repo/random/some_folder/
There are many examples of Bash string manipulation:
BashFAQ/100
BashFAQ/073
Bash Hacker's Parameter Expansion
Side note: Avoid using CAPITAL_NAMES for Bash variables. They are reserved for Bash use by convention...
You want parameter expansion, not command substitution.
RESULT="${RESULT%/*}/"
I want to make a script that takes a file path for argument, and cds into its folder.
Here is what I made :
#!/bin/bash
#remove the file name, and change every space into \space
shorter=`echo "$1" | sed 's/\/[^\/]*$//' | sed 's/\ /\\\ /g'`
echo $shorter
cd $shorter
I actually have 2 questions (I am a relative newbie to shell scripts) :
How could I make the cd "persistent" ? I want to put this script into /usr/bin, and then call it from wherever in the filesystem. Upon return of the script, I want to stay in the $shorter folder. Basically, if pwd was /usr/bin, I could make it by typing . script /my/path instead of ./script /my/path, but what if I am in an other folder ?
The second question is trickier. My script fails whenever there is a space in the given argument. Although $shorter is exactly what I want (for instance /home/jack/my\ folder/subfolder), cd fails whith the error /usr/bin/script : line 4 : cd: /home/jack/my\: no file or folder of this type. I think I have tried everything, using things like cd '$shorter' or cd "'"$shorter"'" doesn't help. What am I missing ??
Thanks a lot for your answers
in your .bashrc add the following line:
function shorter() { cd "${1%/*}"; }
% means remove the smaller pattern from the end
/* is the patern
Then in your terminal:
$ . ~/.bashrc # to refresh your bash configuration
$ type shorter # to check if your new function is available
shorter is a function
shorter ()
{
cd "${1%/*}"
}
$ shorter ./your/directory/filename # this will move to ./your/directory
The first part:
The change of directory won't be “persistent” beyond the lifetime of your script, because your script runs in a new shell process. You could, however, use a shell alias or a shell function. For example, you could embed the code in a shell function and define it in your .bash_profile or other source location.
mycdfunction () {
cd /blah/foo/"$1"
}
As for the “spaces in names” bit:
The general syntax for referring to a variable in Bourne shells is: "$var" — the "double quotes" tell the shell to expand any variables inside of them, but to group the outcome as a single parameter.
Omitting the double quotes around $var tells the shell to expand the variable, but then split the results into parameters (“words”) on whitespace. This is how the shell splits up parameters, normally.
Using 'single quotes' causes the shell to not expand any contents, but group the parameters togethers.
You can use \ (backslash-blank) to escape a space when you're typing (or in a script), but that's usually harder to read than using 'single quotes' or "double quotes"…
Note that the expansion phase includes: $variables wild?cards* {grouping,names}with-braces $(echo command substitution) and other effects.
| expansion | no expansion
-------------------------------------------------------
grouping | " " | ' '
splitting | (no punc.) | (not easily done)
For the first part, there is no need for the shorter variable at all. You can just do:
#!/bin/bash
cd "${1%/*}"
Explanation
Most shells, including bash, have what is called Parameter Expansion and they are very powerful and efficient as they allow you to manipulate variables nativly within the shell that would normally require a call to an external binary.
Two common examples of where you can use Parameter Expansion over an external call would be:
${var%/*} # replaces dirname
${var##*/} # replaces basename
See this FAQ on Parameter Expansion to learn more. In fact, while you're there might as well go over the whole FAQ
When you put your script inside /usr/bin you can call it anywhere. And to deal with whitespace in the shell just put the target between "" (but this doesn't matter !!).
Well here is a demo:
#!/bin/bash
#you can use dirname but that's not apropriate
#shorter=$(dirname $1)
#Use parameter expansion (too much better)
shorter=${1%/*}
echo $shorter
An alternate way to do it, since you have dirname on your Mac:
#!/bin/sh
cd "$(dirname "$1")"
Since you mentioned in the comments that you wanted to be able to drag files into a window and cd to them, you might want to make your script allow file or directory paths as arguments:
#!/bin/sh
[ -f "$1" ] && set "$(dirname "$1")" # convert a file to a directory
cd "$1"